home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Tools - Objects / MacApp / MacApp 2.0 CD Release / MacApp 2.0 (Many Libraries) / Libraries / UMacApp.TApplication.p < prev    next >
Encoding:
Text File  |  1990-03-27  |  115.4 KB  |  4,458 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UMacApp.TApplication.p }
  4. { Copyright © 1984-1990 by Apple Computer Inc. All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S MAApplicationRes}
  8.  
  9. FUNCTION TCommandList.Compare(item1, item2: TObject): integer;
  10.  
  11.     BEGIN
  12.     IF TCommand(item1).fPriority > TCommand(item2).fPriority THEN
  13.         Compare := kItem1GreaterThanItem2
  14.     ELSE IF TCommand(item1).fPriority < TCommand(item2).fPriority THEN
  15.         Compare := kItem1LessThanItem2
  16.     ELSE
  17.         Compare := kItem1EqualItem2
  18.     END;
  19.  
  20. {--------------------------------------------------------------------------------------------------}
  21. {$S MAInit}
  22.  
  23. PROCEDURE TCommandList.ICommandList;
  24.  
  25.     BEGIN
  26.     ISortedList;
  27.     END;
  28.  
  29. {--------------------------------------------------------------------------------------------------}
  30. {$S MAApplicationRes}
  31.  
  32. PROCEDURE TCommandList.Insert(item: TObject); OVERRIDE;
  33.  
  34.     VAR
  35.         oldObjectPerm: BOOLEAN;
  36.         anEqualItem: ArrayIndex;
  37.         lastEqualItem: ArrayIndex;
  38.         i: ArrayIndex;
  39.  
  40.     BEGIN
  41.     { Guarantee that the insertion can take place }
  42.     oldObjectPerm := AllocateObjectsFromPerm(FALSE);
  43.  
  44.     { !!! the search alg. should support this.  Performance will degrade here for
  45.     big queues (shouldn't happen often, but come back and fix the general case anyways) }
  46.  
  47.     anEqualItem := GetEqualItemNo(item);
  48.  
  49.     { If any equal items were found then find the _last_ equal item }
  50.     IF anEqualItem <> kEmptyIndex THEN
  51.         BEGIN
  52.         lastEqualItem := anEqualItem; { Tentative value }
  53.         FOR i := (anEqualItem + 1) TO GetSize DO    { ??? what about kMaxArrayIndex? }
  54.             IF Compare(At(i), item) = kItem1EqualItem2 THEN
  55.                 lastEqualItem := i
  56.             ELSE
  57.                 LEAVE;
  58.  
  59.         InsertBefore(lastEqualItem + 1, item);
  60.         END
  61.     ELSE
  62.         INHERITED Insert(item);
  63.  
  64.     IF AllocateObjectsFromPerm(oldObjectPerm) THEN;
  65.     END;
  66.  
  67. {--------------------------------------------------------------------------------------------------}
  68. {$S MAFields}
  69.  
  70. PROCEDURE TCommandList.Fields(PROCEDURE DoToField(fieldName: Str255;
  71.                                                   fieldAddr: Ptr;
  72.                                                   fieldType: integer)); OVERRIDE;
  73.  
  74.     BEGIN
  75.     DoToField('TCommandList', NIL, bClass);
  76.     INHERITED Fields(DoToField);
  77.     END;
  78.  
  79. {--------------------------------------------------------------------------------------------------}
  80. {$IFC qDebug}
  81. {$S MADebugger}
  82.  
  83. PROCEDURE TDebugCommand.DoIt;
  84.  
  85.     BEGIN
  86.     EnterMacAppDebugger;
  87.     END;
  88. {$ENDC}
  89.  
  90. {--------------------------------------------------------------------------------------------------}
  91. {$IFC qDebug}
  92. {$S MASelCommand}
  93.  
  94. PROCEDURE TDebugCommand.IDebugCommand(itsCmdNumber: CmdNumber);
  95.  
  96.     BEGIN
  97.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  98.     END;
  99. {$ENDC}
  100.  
  101. {--------------------------------------------------------------------------------------------------}
  102. {$IFC qDebug}
  103. {$S MAFields}
  104.  
  105. PROCEDURE TDebugCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  106.                                                    fieldAddr: Ptr;
  107.                                                    fieldType: integer)); OVERRIDE;
  108.  
  109.     BEGIN
  110.     DoToField('TDebugCommand', NIL, bClass);
  111.     INHERITED Fields(DoToField);
  112.     END;
  113. {$ENDC}
  114.  
  115. {--------------------------------------------------------------------------------------------------}
  116. {$IFC qInspector}
  117. {$S MAInspector}
  118.  
  119. PROCEDURE TInspectorCommand.DoIt;
  120.  
  121.     BEGIN
  122.     MakeInspectorWindow;
  123.     END;
  124. {$ENDC}
  125.  
  126. {--------------------------------------------------------------------------------------------------}
  127. {$IFC qInspector}
  128. {$S MASelCommand}
  129.  
  130. PROCEDURE TInspectorCommand.IInspectorCommand(itsCmdNumber: CmdNumber);
  131.  
  132.     BEGIN
  133.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  134.     END;
  135. {$ENDC}
  136.  
  137. {--------------------------------------------------------------------------------------------------}
  138. {$IFC qInspector}
  139. {$S MAFields}
  140.  
  141. PROCEDURE TInspectorCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  142.                                                        fieldAddr: Ptr;
  143.                                                        fieldType: integer)); OVERRIDE;
  144.  
  145.     BEGIN
  146.     DoToField('TInspectorCommand', NIL, bClass);
  147.     INHERITED Fields(DoToField);
  148.     END;
  149. {$ENDC}
  150.  
  151. {--------------------------------------------------------------------------------------------------}
  152. {$S MAApplicationRes}
  153.  
  154. PROCEDURE TQuitCommand.DoIt;
  155.  
  156.     VAR
  157.         fi:                 FailInfo;
  158.  
  159.     PROCEDURE HdlQuit(error: OSErr;
  160.                       message: LONGINT);
  161.  
  162.         BEGIN
  163.         gAppDone := FALSE;
  164.         END;
  165.  
  166.     BEGIN
  167.     CatchFailures(fi, HdlQuit);
  168.     gAppDone := TRUE;
  169.     gApplication.Close;
  170.     Success(fi);
  171.     END;
  172.  
  173. {--------------------------------------------------------------------------------------------------}
  174. {$S MAInit}
  175.  
  176. PROCEDURE TQuitCommand.IQuitCommand(itsCmdNumber: CmdNumber);
  177.  
  178.     BEGIN
  179.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  180.     END;
  181.  
  182. {--------------------------------------------------------------------------------------------------}
  183. {$S MAFields}
  184.  
  185. PROCEDURE TQuitCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  186.                                                   fieldAddr: Ptr;
  187.                                                   fieldType: integer)); OVERRIDE;
  188.  
  189.     BEGIN
  190.     DoToField('TQuitCommand', NIL, bClass);
  191.     INHERITED Fields(DoToField);
  192.     END;
  193.  
  194. {--------------------------------------------------------------------------------------------------}
  195. {$S MAApplicationRes}
  196.  
  197. PROCEDURE TUndoRedoCommand.DoIt;
  198.  
  199.     VAR
  200.         deltaCount:         integer;
  201.         lastCommand:        TCommand;
  202.  
  203.     BEGIN
  204.     lastCommand := gTarget.GetLastCommand;
  205.     IF lastCommand.fChangesClipboard THEN
  206.         gApplication.SwapClipViews;
  207.  
  208.     IF lastCommand.fCmdDone THEN
  209.         BEGIN
  210.         lastCommand.UndoIt;
  211.         deltaCount := - 1;
  212.         END
  213.     ELSE
  214.         BEGIN
  215.         lastCommand.RedoIt;
  216.         deltaCount := 1;
  217.         END;
  218.  
  219.     lastCommand.fCmdDone := NOT lastCommand.fCmdDone;
  220.  
  221.     IF lastCommand.fCausesChange THEN                    { put this after .UndoIt/.RedoIt, so they
  222.                                                          can change the flag }
  223.         WITH lastCommand DO
  224.             IF fChangedDocument <> NIL THEN
  225.                 WITH fChangedDocument DO
  226.                     BEGIN
  227.                     SetChangeCount(GetChangeCount + deltaCount);
  228.                     {$IFC qDebug}
  229.                     IF GetChangeCount < 0 THEN
  230.                         ProgramBreak('GetChangeCount < 0');
  231.                     {$ENDC}
  232.                     END;
  233.     END;
  234.  
  235. {--------------------------------------------------------------------------------------------------}
  236. {$S MAInit}
  237.  
  238. PROCEDURE TUndoRedoCommand.IUndoRedoCommand(itsCmdNumber: CmdNumber);
  239.  
  240.     BEGIN
  241.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  242.     END;
  243.  
  244. {--------------------------------------------------------------------------------------------------}
  245. {$S MAFields}
  246.  
  247. PROCEDURE TUndoRedoCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  248.                                                       fieldAddr: Ptr;
  249.                                                       fieldType: integer)); OVERRIDE;
  250.  
  251.     BEGIN
  252.     DoToField('TUndoRedoCommand', NIL, bClass);
  253.     INHERITED Fields(DoToField);
  254.     END;
  255.  
  256. {--------------------------------------------------------------------------------------------------}
  257. {$S MAOpen}
  258.  
  259. PROCEDURE TNewDocCommand.DoIt;
  260.  
  261.     BEGIN
  262.     gApplication.OpenNew(fCmdNumber);
  263.     END;
  264.  
  265. {--------------------------------------------------------------------------------------------------}
  266. {$S MASelCommand}
  267.  
  268. PROCEDURE TNewDocCommand.INewDocCommand(itsCmdNumber: CmdNumber);
  269.  
  270.     BEGIN
  271.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  272.     END;
  273.  
  274. {--------------------------------------------------------------------------------------------------}
  275. {$S MAFields}
  276.  
  277. PROCEDURE TNewDocCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  278.                                                     fieldAddr: Ptr;
  279.                                                     fieldType: integer)); OVERRIDE;
  280.  
  281.     BEGIN
  282.     DoToField('TNewDocCommand', NIL, bClass);
  283.     INHERITED Fields(DoToField);
  284.     END;
  285.  
  286. {--------------------------------------------------------------------------------------------------}
  287. {$S MAOpen}
  288.  
  289. PROCEDURE TOldDocCommand.DoIt;
  290.  
  291.     VAR
  292.         anAppFile:            AppFile;
  293.  
  294.     BEGIN
  295.     IF gApplication.ChooseDocument(fCmdNumber, anAppFile) THEN
  296.         gApplication.OpenOld(fCmdNumber, anAppFile);
  297.     END;
  298.  
  299. {--------------------------------------------------------------------------------------------------}
  300. {$S MASelCommand}
  301.  
  302. PROCEDURE TOldDocCommand.IOldDocCommand(itsCmdNumber: CmdNumber);
  303.  
  304.     BEGIN
  305.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  306.     END;
  307.  
  308. {--------------------------------------------------------------------------------------------------}
  309. {$S MAFields}
  310.  
  311. PROCEDURE TOldDocCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  312.                                                     fieldAddr: Ptr;
  313.                                                     fieldType: integer)); OVERRIDE;
  314.  
  315.     BEGIN
  316.     DoToField('TOldDocCommand', NIL, bClass);
  317.     INHERITED Fields(DoToField);
  318.     END;
  319.  
  320. {--------------------------------------------------------------------------------------------------}
  321. {$S MASelCommand}
  322.  
  323. PROCEDURE TAboutAppCommand.IAboutAppCommand(itsCmdNumber: CmdNumber);
  324.  
  325.     BEGIN
  326.     INoChangesCommand(itsCmdNumber, NIL, NIL, NIL);
  327.     END;
  328.  
  329. {--------------------------------------------------------------------------------------------------}
  330. {$S MAAboutApp}
  331.  
  332. PROCEDURE TAboutAppCommand.DoIt;
  333.  
  334.     BEGIN
  335.     gApplication.DoShowAboutApp;
  336.     END;
  337.  
  338. {--------------------------------------------------------------------------------------------------}
  339. {$S MAFields}
  340.  
  341. PROCEDURE TAboutAppCommand.Fields(PROCEDURE DoToField(fieldName: Str255;
  342.                                                       fieldAddr: Ptr;
  343.                                                       fieldType: integer)); OVERRIDE;
  344.  
  345.     BEGIN
  346.     DoToField('TAboutAppCommand', NIL, bClass);
  347.     INHERITED Fields(DoToField);
  348.     END;
  349.  
  350. {--------------------------------------------------------------------------------------------------}
  351. {$S MAInit}
  352.  
  353. PROCEDURE TApplication.IApplication(itsMainFileType: OSType);
  354.  
  355.     CONST
  356.         kParamText1         = '^0';
  357.  
  358.     TYPE
  359.         MenuBarHandle        = ^MenuBarPtr;
  360.         MenuBarPtr            = ^MenuBarRecord;
  361.         MenuBarRecord        = RECORD
  362.             nMenus:             integer;
  363.             menuID:             ARRAY [1..1000] OF integer;
  364.             END;
  365.  
  366.     VAR
  367.         menuID:             integer;
  368.         aMenu:                MenuHandle;
  369.         mbar:                Handle;
  370.         hmbar:                MenuBarHandle;
  371.         i:                    integer;
  372.         s:                    Str255;
  373.         aCommandList:        TCommandList;
  374.         apName:             Str255;
  375.         apRefnum:            integer;
  376.         apParam:            Handle;
  377.  
  378.     BEGIN
  379.     gApplication := SELF;
  380.     gAppDone := FALSE;
  381.     gSysWindowActive := FALSE;
  382.     gTarget := SELF;
  383.     fTicksOfLastIdle := 0;
  384.     fTicksTilNextIdle := 0;
  385.     fCommandQueue := NIL;
  386.     fLastCommand := NIL;
  387.  
  388.     WITH gOldScrapStuff DO
  389.         BEGIN
  390.         scrapSize := 0;
  391.         scrapHandle := NIL;
  392.         scrapCount := 0;
  393.         scrapState := 0;
  394.         scrapName := NIL;
  395.         END;
  396.     gNewScrapStuff := gOldScrapStuff;
  397.  
  398.     IEvtHandler(NIL);
  399.  
  400.     {$IFC qInspector}
  401.     MakeInspector;
  402.     AddObjectToInspector(SELF);
  403.     AddObjectToInspector(gNullPrintHandler);
  404.     AddObjectToInspector(gPrintHandler);
  405.     AddObjectToInspector(gFreeWindowList);
  406.     {$ENDC}
  407.  
  408.     New(aCommandList);
  409.     FailNil(aCommandList);
  410.     aCommandList.ICommandList;
  411.     fCommandQueue := aCommandList;
  412.     {$IFC qDebug}
  413.     fCommandQueue.SetEltType('TCommand');
  414.     {$ENDC}
  415.  
  416.     fLaunchWithNewDocument := TRUE;
  417.  
  418.     gDocList := NewList;
  419.     {$IFC qDebug}
  420.     gDocList.SetEltType('TDocument');
  421.     {$ENDC}
  422.  
  423.     gMainFileType := itsMainFileType;
  424.  
  425.     gVarClipPicSize := FALSE;                            { temporary }
  426.  
  427.     IF NOT gFinderPrinting THEN
  428.         BEGIN
  429.         mbar := MAGetNewMBar(gMBarDisplayed);
  430.         IF mbar <> NIL THEN
  431.             BEGIN
  432.             SetMenuBar(mbar);
  433.             ReleaseResource(Handle(mbar));
  434.             END
  435.         ELSE
  436.             BEGIN
  437.             {$IFC qDebug}
  438.             Writeln('The MBAR ', gMBarDisplayed: 1, ' resource was not specified.');
  439.             ProgramBreak('You will not have any menus!');
  440.             {$ENDC}
  441.             END;
  442.  
  443.         {$IFC qDebug OR qInspector}
  444.         aMenu := GetMenu(mDebug);
  445.         IF aMenu <> NIL THEN
  446.             InsertMenu(aMenu, 0);
  447.         {$ENDC}
  448.  
  449.         aMenu := MAGetMenu(mApple);
  450.         IF aMenu <> NIL THEN
  451.             AddResMenu(aMenu, 'DRVR');
  452.  
  453.         { If the "About" item contains the paramtext keystring (^0) then substitute the
  454.         Application's name }
  455.         CmdToName(cAboutApp, s);
  456.         i := Pos(kParamText1, s);
  457.         IF i <> 0 THEN
  458.             BEGIN
  459.             GetAppParms(apName, apRefnum, apParam);
  460.             Delete(s, i, length(kParamText1));
  461.             Insert(apName, s, i);
  462.             SetCmdName(cAboutApp, s);
  463.             END;
  464.  
  465.         mbar := MAGetNewMBar(gMBarNotDisplayed);        { reads in and initializes these menus. }
  466.         IF mbar <> NIL THEN
  467.             ReleaseResource(Handle(mbar));
  468.  
  469.         IF qNeedsHierarchicalMenus | gConfiguration.hasHierarchicalMenus THEN
  470.             BEGIN
  471.             { Add all the hierarchical menus in the 'hierarchical' menu bar to the applications
  472.             menus.    Note that hierarchical must be treated differently from regular menus in that
  473.             they are added with InsertMenu(…, -1).    We can't use GetNewMBar here because we want
  474.             to call GetMenu for each menu in the MBAR, and GetNewMBar would do that for us.}
  475.             hmbar := MenuBarHandle(GetResource('MBAR', gMBarHierarchical));
  476.             IF hmbar <> NIL THEN
  477.                 BEGIN
  478.                 FOR i := 1 TO hmbar^^.nMenus DO
  479.                     BEGIN
  480.                     aMenu := GetMenu(hmbar^^.menuID[i]);
  481.                     IF aMenu <> NIL THEN
  482.                         InsertMenu(aMenu, - 1);
  483.                     END;
  484.                 ReleaseResource(Handle(hmbar));
  485.                 END;
  486.             END;
  487.  
  488.         gClipWindow := MakeClipboardWindow;
  489.         gClipOrphanage := gClipWindow.FindSubView(KIDClipView);
  490.         FailNILResource(gClipOrphanage);
  491.  
  492.         END;
  493.  
  494.     {
  495.     | Finally finish up with the debugger;
  496.     }
  497.     {$IFC qDebug}
  498.     InitUDebugAfterIApplication;
  499.     {$ENDC}
  500.  
  501.     END;
  502.  
  503. {--------------------------------------------------------------------------------------------------}
  504. {$S MAClipboard}
  505.  
  506. PROCEDURE TApplication.AbandonUndoClipboard;
  507.  
  508.     BEGIN
  509.     IF gClipUndoView <> NIL THEN
  510.         BEGIN
  511.         {$IFC qDebug}
  512.         IF gClipUndoView = gClipView THEN
  513.             ProgramBreak('About to Free view both in clip and undo Clip!');
  514.         {$ENDC}
  515.         gClipUndoView.FreeFromClipboard;
  516.         gClipUndoView := NIL;
  517.         END;
  518.     END;
  519.  
  520. {--------------------------------------------------------------------------------------------------}
  521. {$S MAActivate}
  522.  
  523. PROCEDURE TApplication.AboutToLoseControl(convertClipboard: BOOLEAN);
  524.  
  525.     LABEL 1000;
  526.  
  527.     VAR
  528.         err:                LONGINT;
  529.         fi:                 FailInfo;
  530.         lastCommand:        TCommand;
  531.  
  532.     PROCEDURE PublicizeFailed(error: integer;
  533.                               message: LONGINT);        { ??? ERROR ??? }
  534.  
  535.         BEGIN
  536.         {$IFC qDebug}
  537.         Writeln('Can''t use clipboard data outside this app');
  538.         {$ENDC}
  539.         IF message = 0 THEN
  540.             message := msgExportClipFailed;
  541.         ShowError(error, message);
  542.         GOTO 1000;
  543.         END;
  544.  
  545.     BEGIN
  546.  { Remember when we last started a desk accessory. UPrinting uses this
  547.   to know whether the Chooser may have been run. }
  548.     gLastDeskAcc := TickCount;
  549.  
  550.     ActivateBusyCursor(FALSE);                            { Don't want busy cursor while in desk acc.}
  551.  
  552.     IF convertClipboard THEN
  553.         BEGIN
  554.         lastCommand := GetLastCommand;
  555.         IF (lastCommand <> NIL) & lastCommand.fChangesClipboard THEN
  556.             CommitLastCommand;
  557.  
  558.         IF (gClipView <> NIL) & (NOT gClipWrittenToDeskScrap) THEN
  559.             BEGIN
  560.             err := ZeroScrap;
  561.             CatchFailures(fi, PublicizeFailed);
  562.             gClipView.WriteToDeskScrap;
  563.             Success(fi);
  564.             gClipWrittenToDeskScrap := TRUE;
  565.         1000:
  566.             AbsorbScrapStuff;                            { ??? correct post-error reentry point? }
  567.             END;
  568.         END;
  569.     END;
  570.  
  571. {--------------------------------------------------------------------------------------------------}
  572. {$S MAApplicationRes}
  573.  
  574. PROCEDURE TApplication.AbsorbScrapStuff;
  575.  
  576.     BEGIN
  577.     gOldScrapStuff := gNewScrapStuff;                    { stash previous version, for later
  578.                                                          change-checkage }
  579.     gNewScrapStuff := InfoScrap^;                        { Copy over from low memory to our private
  580.                                                          global record }
  581.     END;
  582.  
  583. {--------------------------------------------------------------------------------------------------}
  584. {$S MAApplicationRes}
  585.  
  586. PROCEDURE TApplication.ActivateBusyCursor(entering: BOOLEAN);
  587.  
  588.     BEGIN
  589.     BusyActivate(entering);
  590.     END;
  591.  
  592. {--------------------------------------------------------------------------------------------------}
  593. {$S MAOpen}
  594.  
  595. PROCEDURE TApplication.AddDocument(aNewDocument: TDocument);
  596.  
  597.     BEGIN
  598.     gDocList.Insert(aNewDocument);
  599.     END;
  600.  
  601. {--------------------------------------------------------------------------------------------------}
  602. {$S MAOpen}
  603.  
  604. PROCEDURE TApplication.AddFreeWindow(aWindow: TWindow);
  605.  
  606.     BEGIN
  607.     gFreeWindowList.Insert(aWindow);
  608.     END;
  609.  
  610. {--------------------------------------------------------------------------------------------------}
  611. {$S MAFile}
  612.  
  613. FUNCTION TApplication.AlreadyOpen(fileName: Str255;
  614.                                   volRefnum: integer): TDocument;
  615.  
  616.     CONST
  617.         ignoreCase            = FALSE;
  618.         diacritSens         = TRUE;
  619.  
  620.     VAR
  621.         parmDirID:            LONGINT;
  622.         parmVRefnum:        integer;
  623.         result:             TDocument;
  624.         err:                OSErr;
  625.  
  626.     PROCEDURE TestDoc(doc: TDocument);
  627.  
  628.         VAR
  629.             err:                OSErr;
  630.             docVRefnum:         integer;
  631.             docDirID:            LONGINT;
  632.  
  633.         BEGIN
  634.         IF (result = NIL) & doc.fSaveExists THEN
  635.             BEGIN
  636.             docVRefnum := doc.fVolRefnum;
  637.             err := GetDirID(docVRefnum, docDirID);
  638.             IF (err = noErr) & (docVRefnum = parmVRefnum) & (docDirID = parmDirID) THEN
  639.                 BEGIN
  640.                 {$Push} {$H-}                            { EqualString does not move memory }
  641.                 IF EqualString(fileName, doc.fTitle^^, ignoreCase, diacritSens) THEN
  642.                     result := doc;
  643.                 {$Pop}
  644.                 END;
  645.             END;
  646.         END;
  647.  
  648.     BEGIN
  649.     result := NIL;
  650.  
  651.     parmVRefnum := volRefnum;
  652.     err := GetDirID(parmVRefnum, parmDirID);
  653.  
  654.     IF err = noErr THEN
  655.         ForAllDocumentsDo(TestDoc);
  656.  
  657.     AlreadyOpen := result;
  658.     END;
  659.  
  660. {--------------------------------------------------------------------------------------------------}
  661. {$S MAApplicationRes}
  662.  
  663. PROCEDURE TApplication.Beep(duration: integer);
  664.  
  665.     BEGIN
  666.     SysBeep(duration);
  667.     END;
  668.  
  669. {--------------------------------------------------------------------------------------------------}
  670.  
  671. FUNCTION CallFileFilter(paramBlock: HParmBlkPtr;
  672.                         routine: ProcPtr): BOOLEAN;
  673.     INLINE $205F,                                        { MOVEA.L (A7)+,A0 }
  674.            $4E90;                                        { JSR (A0) }
  675.  
  676.  { This is called only when opening/printing from the finder; it simulates the
  677.   filtering done by Std File. }
  678.  
  679. {--------------------------------------------------------------------------------------------------}
  680. {$S MAFinder}
  681.  
  682. FUNCTION TApplication.CanOpenDocument(itsCmdNumber: CmdNumber;
  683.                                       VAR anAppFile: AppFile): BOOLEAN;
  684.  
  685.     VAR
  686.         dlgID:                integer;
  687.         where:                Point;
  688.         fileFilter:         ProcPtr;
  689.         dlgHook:            ProcPtr;
  690.         filterProc:         ProcPtr;
  691.         typeList:            TypeListHandle;
  692.         i:                    integer;
  693.         paramBlock:         HParamBlockRec;
  694.         numTypes:            integer;
  695.  
  696.     BEGIN
  697.     CanOpenDocument := FALSE;
  698.  
  699.   { First check that file type is in the list of allowed file types. See SFGetParms
  700.    below for more info. }
  701.     typeList := TypeListHandle(NewHandle(0));
  702.     FailNil(typeList);
  703.  
  704.     SFGetParms(itsCmdNumber, dlgID, where, fileFilter, dlgHook, filterProc, typeList);
  705.  
  706.     numTypes := GetHandleSize(Handle(typeList)) DIV SIZEOF(ResType);
  707.     IF numTypes = 0 THEN
  708.         CanOpenDocument := TRUE                         { if 0 then want all types }
  709.     ELSE
  710.         FOR i := 1 TO numTypes DO
  711.  { do coercions because the compiler generates lousy code for comparing 2
  712.   packed arrays of characters }
  713.             IF LONGINT(anAppFile.fType) = LONGINT(typeList^^[i]) THEN
  714.                 BEGIN
  715.                 IF fileFilter = NIL THEN
  716.                     CanOpenDocument := TRUE
  717.                 ELSE IF GetFileInfo(anAppFile.fName, anAppFile.vRefnum, paramBlock) = noErr THEN
  718.                     CanOpenDocument := NOT CallFileFilter(@paramBlock, fileFilter)
  719.                 ELSE
  720.                     CanOpenDocument := FALSE;
  721.                 LEAVE;
  722.                 END;
  723.  
  724.     Handle(typeList) := DisposeIfHandle(typeList);
  725.     END;
  726.  
  727. {--------------------------------------------------------------------------------------------------}
  728. {$S MAApplicationRes}
  729.  
  730. PROCEDURE TApplication.CheckDeskScrap;
  731.  
  732.     VAR
  733.         err:                OSErr;
  734.         lastCommand:        TCommand;
  735.  
  736.     BEGIN
  737.     AbsorbScrapStuff;
  738.  
  739.     IF (gOldScrapStuff.scrapCount <> gNewScrapStuff.scrapCount) THEN
  740.         BEGIN
  741.         lastCommand := GetLastCommand;
  742.         IF (lastCommand <> NIL) & lastCommand.fChangesClipboard THEN
  743.             CommitLastCommand;
  744.         gClipView.FreeFromClipboard;                    { AbandonCurrentClipboard }
  745.         gClipView := NIL;                                { no reason to have an Undo clipboard }
  746.  
  747.         { If the scrap is in memory and we are low on memory, then write the scrap to disk.}
  748.         IF (gNewScrapStuff.scrapState > 0) & MemSpaceIsLow THEN
  749.             err := UnloadScrap;                         { Write the scrap to disk. How should we
  750.                                                          handle the error??? }
  751.         ReadFromDeskScrap;
  752.         END;
  753.     END;
  754.  
  755. {--------------------------------------------------------------------------------------------------}
  756. {$S MAOpen}
  757.  
  758. FUNCTION TApplication.ChooseDocument(itsCmdNumber: CmdNumber;
  759.                                      VAR anAppFile: AppFile): BOOLEAN;
  760.  
  761.     TYPE
  762.         SFTypeListHandle    = ^SFTypeListPtr;
  763.         SFTypeListPtr        = ^SFTypeList;
  764.  
  765.     VAR
  766.         dlgID:                integer;
  767.         where:                Point;
  768.         fileFilter:         ProcPtr;
  769.         dlgHook:            ProcPtr;
  770.         filterProc:         ProcPtr;
  771.         typeList:            TypeListHandle;
  772.         pTypeList:            SFTypeListPtr;
  773.         numTypes:            integer;
  774.         reply:                SFReply;
  775.  
  776.     BEGIN
  777.     typeList := TypeListHandle(NewHandle(0));
  778.     FailNil(typeList);
  779.  
  780.     SFGetParms(itsCmdNumber, dlgID, where, fileFilter, dlgHook, filterProc, typeList);
  781.     numTypes := GetHandleSize(Handle(typeList)) DIV SIZEOF(ResType);
  782.  
  783.     IF numTypes = 0 THEN
  784.         BEGIN
  785.         numTypes := - 1;                                { Tell Std File to display all types.}
  786.         pTypeList := @pTypeList;                        { arbitrary, as long as it points to 4 bytes
  787.                                                          of valid memory }
  788.         END
  789.     ELSE
  790.         BEGIN
  791.         LockHandleHigh(Handle(typeList));                { in case Std File does allocations }
  792.         pTypeList := SFTypeListHandle(typeList)^;
  793.         END;
  794.  
  795.     {$IFC qDebug}
  796.     { Causes TApplication.GetEvent to call CheckRsrcUsage. }
  797.     gRsrcCheck := 0;
  798.     {$ENDC}
  799.  
  800.     UpdateAllWindows;                                    { needed to work around bug in SF; if all
  801.                                                          windows are not updated you wont be able
  802.                                                          to mount a disk correctly }
  803.  
  804.     SFPGetFile(where, '', fileFilter, numTypes, pTypeList^, dlgHook, reply, dlgID, filterProc);
  805.  
  806.     Handle(typeList) := DisposeIfHandle(typeList);
  807.  
  808.     ChooseDocument := reply.good;
  809.     IF reply.good THEN
  810.         BEGIN
  811.         anAppFile.vRefnum := reply.vRefnum;
  812.         anAppFile.fType := reply.fType;
  813.         anAppFile.versNum := reply.version;
  814.         anAppFile.fName := reply.fName;
  815.         END;
  816.     END;
  817.  
  818. {--------------------------------------------------------------------------------------------------}
  819. {$S MAClipboard}
  820.  
  821. PROCEDURE TApplication.ClaimClipboard(clipView: TView);
  822.  
  823.     BEGIN
  824.     AbandonUndoClipboard;                                { free up any old UNDO stuff }
  825.     gClipUndoView := gClipView;                         { Copy current clipboard contents to the
  826.                                                          Undo side }
  827.     IF clipView <> NIL THEN
  828.         SetClipView(clipView)                            { Will install it as gClipView }
  829.     ELSE
  830.         BEGIN
  831.         {$IFC qDebug}
  832.         ProgramBreak('Claiming clipboard with null view');
  833.         {$ENDC}
  834.         END;
  835.  
  836.     gClipClaimed := TRUE;
  837.     END;
  838.  
  839. {--------------------------------------------------------------------------------------------------}
  840. {$S MATerminate}
  841.  
  842. PROCEDURE TApplication.Close;
  843.  
  844.     VAR
  845.         WMgrWindow:         WindowPtr;
  846.  
  847.     PROCEDURE FreeIt(anEvtHandler: TEvtHandler);
  848.  
  849.         BEGIN
  850.         FreeIfObject(anEvtHandler);                     { ??? also call Terminate ??? }
  851.         anEvtHandler := NIL;
  852.         END;
  853.  
  854.     PROCEDURE CloseADocument(aDocument: TDocument);
  855.  
  856.         BEGIN
  857.         aDocument.Close;
  858.         END;
  859.  
  860.     BEGIN
  861.     { Close all of the windows }
  862.     REPEAT
  863.         WMgrWindow := FrontWindow;
  864.         IF WMgrWindow <> NIL THEN
  865.             CloseWMgrWindow(WMgrWindow);
  866.     UNTIL WMgrWindow = NIL;
  867.  
  868.     { Close any windowless documents }
  869.     ForAllDocumentsDo(CloseADocument);
  870.  
  871.     gPrintHandler.Terminate;
  872.     IF gHeadCoHandler <> NIL THEN
  873.         gHeadCoHandler.EachHandler(FreeIt);
  874.     IF LoadScrap <> noErr THEN;                         { ??? }
  875.     END;
  876.  
  877. {--------------------------------------------------------------------------------------------------}
  878. {$S MAClose}
  879.  
  880. PROCEDURE TApplication.CloseWMgrWindow(aWMgrWindow: WindowPtr);
  881.  
  882.     VAR
  883.         aWindow:            TWindow;
  884.  
  885.     BEGIN
  886.     IF IsDeskAccessory(aWMgrWindow) THEN
  887.         CloseDeskAcc(WindowPeek(aWMgrWindow)^.windowKind)
  888.     ELSE
  889.         BEGIN
  890.         aWindow := WMgrToWindow(aWMgrWindow);
  891.         IF aWindow <> NIL THEN
  892.             aWindow.CloseByUser
  893.         ELSE
  894.             HideWindow(aWMgrWindow);
  895.         END;
  896.     END;
  897.  
  898. {--------------------------------------------------------------------------------------------------}
  899. {$S MAApplicationRes}
  900.  
  901. PROCEDURE TApplication.CommitLastCommand;
  902.  
  903.     BEGIN
  904.     AbandonUndoClipboard;
  905.  
  906.     IF fLastCommand <> NIL THEN
  907.         BEGIN
  908.         IF fLastCommand.fCmdDone THEN
  909.             fLastCommand.Commit;
  910.         IF fLastCommand.fFreeOnCompletion THEN
  911.             FreeIfObject(fLastCommand);
  912.         fLastCommand := NIL;
  913.         END;
  914.     END;
  915.  
  916. {--------------------------------------------------------------------------------------------------}
  917. {$S MAApplicationRes}
  918.  
  919. FUNCTION TApplication.CountClicks(aPDownEvent: EventRecordPtr;
  920.                                   whereMouseDown: integer): integer;
  921.  
  922.     VAR
  923.         clickCount:         integer;
  924.  
  925.     BEGIN
  926.     clickCount := 1;
  927.  
  928.     WITH aPDownEvent^ DO
  929.         BEGIN
  930.         { This series of IF's generates less code than short-circuit booleans }
  931.         IF whereMouseDown = gLastClickPart THEN
  932.             IF gClickCount > 0 THEN                     { not the first click and ... }
  933.                 IF when - gLastUpTime < GetDblTime THEN { ... close enough in time and ... }
  934.                     IF gTarget.DoMultiClick(gLastMsePt, where) { ... close enough in space } THEN
  935.                         clickCount := gClickCount + 1;
  936.  
  937.         gLastMsePt := where;
  938.         END;
  939.  
  940.     gLastClickPart := whereMouseDown;
  941.     gClickCount := clickCount;
  942.     CountClicks := clickCount;
  943.     END;
  944.  
  945. {--------------------------------------------------------------------------------------------------}
  946. {$S MAClose}
  947.  
  948. PROCEDURE TApplication.DeleteDocument(docToDelete: TDocument);
  949.  
  950.     BEGIN
  951.     gDocList.Delete(docToDelete);
  952.     END;
  953.  
  954. {--------------------------------------------------------------------------------------------------}
  955. {$S MAApplicationRes}
  956.  
  957. PROCEDURE TApplication.DeleteFreeWindow(windowToDelete: TWindow);
  958.  
  959.     BEGIN
  960.     gFreeWindowList.Delete(windowToDelete);
  961.     END;
  962.  
  963. {--------------------------------------------------------------------------------------------------}
  964. {$S MAApplicationRes}
  965.  
  966. PROCEDURE TApplication.DispatchEvent(VAR theEventInfo: EventInfo;
  967.                                      VAR commandToPerform: TCommand);
  968.  
  969.     BEGIN
  970.     commandToPerform := NIL;
  971.  
  972.     WITH theEventInfo.thePEvent^ DO
  973.         BEGIN
  974.  
  975.         CASE what OF
  976.             mouseUp:
  977.                 commandToPerform := HandleMouseUp(theEventInfo);
  978.  
  979.             mouseDown:
  980.                 commandToPerform := HandleMouseDown(theEventInfo);
  981.  
  982.             activateEvt:
  983.                 commandToPerform := HandleActivateEvent(theEventInfo);
  984.  
  985.             updateEvt:
  986.                 commandToPerform := HandleUpdateEvent(theEventInfo);
  987.  
  988.             keyDown, autoKey:
  989.                 commandToPerform := HandleKeyDownEvent(theEventInfo);
  990.  
  991.             keyUp:
  992.                 { !!! We'd like to have a chain for keyUp but a MultiFinder™ bug
  993.                 (at least up to 6.0) keep us from reliably getting keyUp events
  994.                 after minor context switches (background updates, etc.).  It replaces
  995.                 the global event mask (which we would have had to change to get keyups
  996.                 in the first place) with the wrong mask.  Oh well, we had such good intentions! } ;
  997.  
  998.             diskEvt:
  999.                 commandToPerform := HandleDiskEvent(theEventInfo);
  1000.  
  1001.             app4Evt:
  1002.             { All app4Evt's are owned by the system }
  1003.                 commandToPerform := HandleSystemEvent(theEventInfo);
  1004.  
  1005.             OTHERWISE
  1006.                 commandToPerform := HandleAlienEvent(theEventInfo);
  1007.  
  1008.         END;
  1009.  
  1010.         END;
  1011.     END;
  1012.  
  1013. {--------------------------------------------------------------------------------------------------}
  1014. {$S MAApplicationRes}
  1015.  
  1016. FUNCTION TApplication.DoCommandKey(ch: CHAR;
  1017.                                    VAR info: EventInfo): TCommand; OVERRIDE;
  1018.  
  1019.     BEGIN
  1020.     DoCommandKey := NIL;
  1021.     IF (NOT info.theAutoKey) & (NOT InModalMenuState) THEN
  1022.         BEGIN
  1023.         SetupTheMenus;
  1024.         { If you want to have case sensitive command keys use the following line because
  1025.         KeyEventToComponents returns the correct character for shifted keys when the command
  1026.         key is down.  That lets us test for things like command-period correctly.  So… in order
  1027.         to be backward compatible (sigh) we now have to ignore the _correct_ char that is passed
  1028.         in (and is in info.theCharacter) and use the old ToolBox supplied unPasteurized character that
  1029.         is left in the actual EventRecord at info.thePEvent^ }
  1030.  
  1031.         { DoCommandKey := MenuEvent(MenuKey(ch)); }
  1032.  
  1033.         DoCommandKey := MenuEvent(MenuKey(chr(BAND(info.thePEvent^.message, charCodeMask))));
  1034.  
  1035.         END;
  1036.     END;
  1037.  
  1038. {--------------------------------------------------------------------------------------------------}
  1039. {$S MAApplicationRes}
  1040.  
  1041. FUNCTION TApplication.DoKeyCommand(ch: CHAR;
  1042.                                    aKeyCode: integer;
  1043.                                    VAR info: EventInfo): TCommand; OVERRIDE;
  1044.  
  1045.     PROCEDURE HandleFunctionKey(cmd: CmdNumber);
  1046.  
  1047.         BEGIN
  1048.         SetupTheMenus;
  1049.         IF CmdEnabled(cmd) THEN
  1050.             DoKeyCommand := gTarget.DoMenuCommand(cmd);
  1051.         END;
  1052.  
  1053.     BEGIN
  1054.     DoKeyCommand := NIL;
  1055.     CASE aKeyCode OF
  1056.         kF1VirtualCode:
  1057.             HandleFunctionKey(cUndo);
  1058.         kF2VirtualCode:
  1059.             HandleFunctionKey(cCut);
  1060.         kF3VirtualCode:
  1061.             HandleFunctionKey(cCopy);
  1062.         kF4VirtualCode:
  1063.             HandleFunctionKey(cPaste);
  1064.         kClearVirtualCode:
  1065.             HandleFunctionKey(cClear);
  1066.         OTHERWISE
  1067.             DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
  1068.     END;
  1069.     END;
  1070.  
  1071. {--------------------------------------------------------------------------------------------------}
  1072. {$S MAOpen}
  1073.  
  1074. FUNCTION TApplication.DoMakeDocument(itsCmdNumber: CmdNumber): TDocument;
  1075. { E X A M P L E
  1076.     VAR aYOURDocument: TDocument;
  1077.  
  1078.     BEGIN
  1079.     New(aYOURDocument);
  1080.     aYOURDocument.IYOURDocument(itsDocKind, ...);
  1081.     DoMakeDocument := aYOURDocument;
  1082.     END;
  1083.  }
  1084.  
  1085.     VAR
  1086.         aDocument:            TDocument;
  1087.  
  1088.     BEGIN
  1089.     { Allocate and initialize the document}
  1090.     aDocument := NIL;
  1091.  
  1092.     IF qTemplateViews THEN
  1093.         aDocument := TDocument(NewStdObject(kStdDocument))
  1094.     ELSE
  1095.         New(aDocument);
  1096.  
  1097.     FailNil(aDocument);
  1098.  
  1099.     aDocument.IDocument(gMainFileType, '????', kUsesDataFork, NOT kUsesRsrcFork, NOT kDataOpen,
  1100.                         NOT kRsrcOpen);
  1101.     DoMakeDocument := aDocument;
  1102.     END;
  1103.  
  1104. {--------------------------------------------------------------------------------------------------}
  1105. {$S MASelCommand}
  1106.  
  1107. FUNCTION TApplication.DoMenuCommand(aCmdNumber: CmdNumber): TCommand;
  1108.  
  1109.     VAR
  1110.         succeeded:            BOOLEAN;
  1111.         aDocument:            TDocument;
  1112.         aWindow:            TWindow;
  1113.         aNewDocCommand:     TNewDocCommand;
  1114.         aOldDocCommand:     TOldDocCommand;
  1115.         aAboutAppCommand:    TAboutAppCommand;
  1116.         aQuitCommand:        TQuitCommand;
  1117.         aUndoRedoCommand:    TUndoRedoCommand;
  1118.  
  1119.         oldObjectPerm:        BOOLEAN;
  1120.         just:                INTEGER;
  1121.  
  1122.         {$IFC qDebug}
  1123.         aDebugCommand:        TDebugCommand;
  1124.         oldState:            BOOLEAN;
  1125.         {$ENDC}
  1126.  
  1127.         {$IFC qInspector}
  1128.         aInspectorCommand:    TInspectorCommand;
  1129.         oldIState:            BOOLEAN;
  1130.         {$ENDC}
  1131.  
  1132.     BEGIN
  1133.     { ==================================================================================
  1134.     Some commands will be returned to perform actions that must _ALWAYS_ be available.
  1135.     The allocation cannot be allowed to fail.  So we do a temp allocation which by
  1136.     definition cannot be allowed to fail.  This strategy is used wherever we want to use
  1137.     command objects but don't want to leave the user twisting in the breeze.
  1138.     NOTE: Don't forget to allow for this memory in your mem! resource if you copy this
  1139.     style in your own code.
  1140.     ================================================================================== }
  1141.  
  1142.     aWindow := GetActiveWindow;
  1143.     DoMenuCommand := NIL;
  1144.  
  1145.     CASE aCmdNumber OF
  1146.         cQuit:
  1147.             BEGIN
  1148.  
  1149.             oldObjectPerm := AllocateObjectsFromPerm(FALSE);
  1150.             New(aQuitCommand);
  1151.             IF AllocateObjectsFromPerm(oldObjectPerm) THEN;
  1152.  
  1153.             FailNil(aQuitCommand);                        { just in case }
  1154.             aQuitCommand.IQuitCommand(aCmdNumber);
  1155.             DoMenuCommand := aQuitCommand;
  1156.             END;
  1157.  
  1158.         cNew..cNewLast, cFinderNew:
  1159.             BEGIN
  1160.             New(aNewDocCommand);
  1161.             FailNil(aNewDocCommand);
  1162.             aNewDocCommand.INewDocCommand(aCmdNumber);
  1163.             DoMenuCommand := aNewDocCommand;
  1164.             END;
  1165.  
  1166.         cOpen..cOpenLast:
  1167.             BEGIN
  1168.             New(aOldDocCommand);
  1169.             FailNil(aOldDocCommand);
  1170.             aOldDocCommand.IOldDocCommand(aCmdNumber);
  1171.             DoMenuCommand := aOldDocCommand;
  1172.             END;
  1173.  
  1174.         cClose:
  1175.             BEGIN
  1176.             IF qDebug & (WMgrToWindow(FrontWindow) <> NIL) THEN
  1177.                 ProgramBreak(
  1178. 'The frontmost window is a window object but didn''t handle the cClose CmdNumber, your TWindow subclass probably forgot to call INHERITED DoMenuCommand!'
  1179.                              );
  1180.  
  1181.             CloseWMgrWindow(FrontWindow);                { TWindow would have handled the command
  1182.                                                          before we get here so the window is
  1183.                                                          probably a DA or something }
  1184.             END;
  1185.  
  1186.         cShowClipboard:
  1187.             IF gClipWindow = aWindow THEN
  1188.                 gClipWindow.Close                        { Hide the clipboard }
  1189.             ELSE
  1190.                 BEGIN
  1191.                 gClipWindow.Open;
  1192.                 gClipWindow.Select;
  1193.                 END;
  1194.  
  1195.         cAboutApp:
  1196.             BEGIN
  1197.             New(aAboutAppCommand);
  1198.             FailNil(aAboutAppCommand);
  1199.             aAboutAppCommand.IAboutAppCommand(aCmdNumber);
  1200.             DoMenuCommand := aAboutAppCommand;
  1201.             END;
  1202.  
  1203.         {$IFC qDebug}
  1204.         cDebugWind:
  1205.             DebugShowTranscriptWindow;
  1206.         cExperimenting:
  1207.             gExperimenting := NOT gExperimenting;
  1208.         cReportEvt:
  1209.             gReportEvt := NOT gReportEvt;
  1210.         cDebugPrinting:
  1211.             gDebugPrinting := NOT gDebugPrinting;
  1212.         cReportMenuChoices:
  1213.             gReportMenuChoices := NOT gReportMenuChoices;
  1214.         cIntenseDebugging:
  1215.             gIntenseDebugging := NOT gIntenseDebugging;
  1216.         cIdentifySoftware:
  1217.             BEGIN
  1218.             Writeln;
  1219.             Writeln('===== Software Version(s): =====');
  1220.             Writeln(kCopyright);
  1221.             gTarget.IdentifySoftware;
  1222.             END;
  1223.         cRefreshFrontWindow:
  1224.             IF aWindow <> NIL THEN
  1225.                 aWindow.ForceRedraw;
  1226.         cModalToggle:
  1227.             IF aWindow <> NIL THEN
  1228.                 aWindow.fIsModal := NOT aWindow.fIsModal;
  1229.         cDoFirstClick:
  1230.             IF aWindow <> NIL THEN
  1231.                 aWindow.fDoFirstClick := NOT aWindow.fDoFirstClick;
  1232.         cSetSysJust:
  1233.             BEGIN
  1234.             { swap the current setting }
  1235.             IF GetActualJustification(teJustSystem) = teJustLeft THEN
  1236.                 just := teJustRight
  1237.             ELSE
  1238.                 just := teJustLeft;
  1239.  
  1240.             { stuff the new setting }
  1241.             IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  1242.                 SetSysJust(just)
  1243.             ELSE IF qNeedsROM128k | gConfiguration.hasROM128k THEN
  1244.                 IntegerPtr(kLMTESysJust)^ := just;
  1245.             END;
  1246.  
  1247.         cEnterMacAppDebugger:
  1248.             BEGIN
  1249.             oldObjectPerm := AllocateObjectsFromPerm(FALSE);
  1250.             oldState := AddNewObjectsToInspector(FALSE);
  1251.             New(aDebugCommand);
  1252.             IF AddNewObjectsToInspector(oldState) THEN;
  1253.             IF AllocateObjectsFromPerm(oldObjectPerm) THEN;
  1254.  
  1255.             FailNil(aDebugCommand);                     { just in case }
  1256.             aDebugCommand.IDebugCommand(aCmdNumber);
  1257.             DoMenuCommand := aDebugCommand;
  1258.             END;
  1259.         {$ENDC}
  1260.  
  1261.         {$IFC qDebug}
  1262.         cTraceSetupMenus:
  1263.             gTraceSetupMenus := NOT gTraceSetupMenus;
  1264.         cTraceIdle:
  1265.             gTraceIdle := NOT gTraceIdle;
  1266.         {$ENDC}
  1267.  
  1268.         {$IFC qInspector}
  1269.         cNewInspectorWindow:
  1270.             BEGIN
  1271.             oldIState := AddNewObjectsToInspector(FALSE);
  1272.             New(aInspectorCommand);
  1273.             IF AddNewObjectsToInspector(oldIState) THEN;
  1274.             FailNil(aInspectorCommand);
  1275.             aInspectorCommand.IInspectorCommand(aCmdNumber);
  1276.             DoMenuCommand := aInspectorCommand;
  1277.             END;
  1278.         {$ENDC}
  1279.  
  1280.         cUndo                                            { , cRedo } :
  1281.             BEGIN
  1282.             oldObjectPerm := AllocateObjectsFromPerm(FALSE);
  1283.             New(aUndoRedoCommand);
  1284.             IF AllocateObjectsFromPerm(oldObjectPerm) THEN;
  1285.  
  1286.             FailNil(aUndoRedoCommand);                    { just in case }
  1287.             aUndoRedoCommand.IUndoRedoCommand(aCmdNumber);
  1288.             DoMenuCommand := aUndoRedoCommand;
  1289.             END;
  1290.  
  1291.         OTHERWISE
  1292.             DoMenuCommand := INHERITED DoMenuCommand(aCmdNumber);
  1293.     END;
  1294.     END;
  1295.  
  1296. {--------------------------------------------------------------------------------------------------}
  1297. {$S MAApplicationRes}
  1298.  
  1299. PROCEDURE TApplication.DoSetupMenus;
  1300.  
  1301.     VAR
  1302.         lowSpace:            BOOLEAN;
  1303.         aWindowPtr:         WindowPtr;
  1304.  
  1305.     BEGIN
  1306.     INHERITED DoSetupMenus;
  1307.  
  1308.     lowSpace := MemSpaceIsLow;
  1309.  
  1310.     Enable(cAboutApp, TRUE);
  1311.  
  1312.     Enable(cQuit, gEventLevel <= 1);                    { Can't enable Quit if in nested event
  1313.                                                          handling }
  1314.     Enable(cShowClipboard, TRUE);
  1315.     SetMenuState(cShowClipboard, kIDBuzzString, bzShowClip, bzHideClip, gClipWindow =
  1316.                  GetActiveWindow);
  1317.  
  1318.     Enable(cNew, NOT lowSpace);
  1319.     Enable(cOpen, NOT lowSpace);
  1320.  
  1321.     aWindowPtr := FrontWindow;
  1322.     IF (aWindowPtr <> NIL) & (WMgrToWindow(aWindowPtr) = NIL) THEN
  1323.         Enable(cClose, WindowPeek(aWindowPtr)^.goAwayFlag <> FALSE); { window objects will take care
  1324.                                                                       of themselves, but we take
  1325.                                                                       care of the indigent. }
  1326.     END;
  1327.  
  1328. {--------------------------------------------------------------------------------------------------}
  1329. {$S MAAboutApp}
  1330.  
  1331. VAR
  1332.     hadCreditsStringList: BOOLEAN;                        { does the rsrc 'STR#' = kDefaultCredits
  1333.                                                          exist ? }
  1334.     lastCreditsStringIndex: integer;                    { the last string in the STR# to be
  1335.                                                          displayed }
  1336.     lastCreditsShownTicks: LONGINT;                     { the tickcount when the last Credit was
  1337.                                                          Shown }
  1338.     originalText:        StringHandle;                    { the about box's original text (prior to
  1339.                                                          credits) }
  1340.     waitTicks:            integer;                        { how long to wait between credits }
  1341.  
  1342. FUNCTION DoShowAboutAppFilter(theDialog: DialogPtr;
  1343.                               VAR theEvent: EventRecord;
  1344.                               VAR itemHit: integer): BOOLEAN;
  1345.  
  1346.     VAR
  1347.         s:                    Str255;
  1348.         originalStr:        Str255;
  1349.         item:                Handle;
  1350.  
  1351.     FUNCTION GetFirstStaticText(theDialog: DialogPtr): Handle;
  1352.  
  1353.         VAR
  1354.             itemType:            integer;
  1355.             item:                Handle;
  1356.             itemNo:             integer;
  1357.             box:                Rect;
  1358.  
  1359.         BEGIN
  1360.         GetFirstStaticText := NIL;
  1361.         itemNo := 1;
  1362.         REPEAT
  1363.             item := NIL;
  1364.             GetDItem(theDialog, itemNo, itemType, item, box);
  1365.             IF BAND(itemType, $7F) = statText THEN        { we don't care if its enabled or not }
  1366.                 BEGIN
  1367.                 GetFirstStaticText := item;
  1368.                 LEAVE;
  1369.                 END
  1370.             ELSE
  1371.                 itemNo := succ(itemNo);
  1372.         UNTIL item = NIL;
  1373.         END;
  1374.  
  1375.     PROCEDURE DoKeyDown(itemNo: integer);
  1376.     { Handle a keypress that has been mapped to the OK button. }
  1377.  
  1378.         VAR
  1379.             itemType:            integer;
  1380.             item:                Handle;
  1381.             finalTicks:         LONGINT;
  1382.             box:                Rect;
  1383.  
  1384.         BEGIN
  1385.         DoShowAboutAppFilter := TRUE;
  1386.         itemHit := itemNo;
  1387.         GetDItem(theDialog, itemNo, itemType, item, box);
  1388.         IF itemType = (ctrlItem + btnCtrl) THEN
  1389.             BEGIN                                        { this code gives visual feedback }
  1390.             HiliteControl(ControlHandle(item), inButton); { hilite the button }
  1391.             Delay(8, finalTicks);                        { delay for 8 ticks }
  1392.             HiliteControl(ControlHandle(item), 0);        { stop hiliting the button }
  1393.             END;
  1394.         END;
  1395.  
  1396.     BEGIN
  1397.     DoShowAboutAppFilter := FALSE;
  1398.  
  1399.     CASE theEvent.what OF
  1400.         keyDown:
  1401.             CASE chr(BAND(theEvent.message, charCodeMask)) OF
  1402.                 chEnter, chReturn:
  1403.                     DoKeyDown(ok);
  1404.             END;
  1405.         nullEvent:
  1406.             IF (TickCount - lastCreditsShownTicks) > waitTicks THEN
  1407.                 BEGIN
  1408.                 item := GetFirstStaticText(theDialog);
  1409.                 GetIndString(s, kDefaultCredits, lastCreditsStringIndex);
  1410.                 IF s <> '' THEN
  1411.                     BEGIN
  1412.                     { save the original text }
  1413.                     IF (lastCreditsStringIndex = 1) & (originalText^^ = '') & (item <> NIL) THEN
  1414.                         BEGIN
  1415.                         GetIText(item, originalStr);
  1416.                         SetString(originalText, originalStr);
  1417.                         END;
  1418.                     lastCreditsStringIndex := succ(lastCreditsStringIndex);
  1419.                     lastCreditsShownTicks := TickCount;
  1420.                     IF item <> NIL THEN
  1421.                         SetIText(item, s);
  1422.                     waitTicks := Min((length(s) * 6), 60);
  1423.                     END
  1424.                 ELSE                                    { no more items }
  1425.                     BEGIN
  1426.                     lastCreditsStringIndex := 1;
  1427.                     lastCreditsShownTicks := TickCount;
  1428.                     IF item <> NIL THEN
  1429.                         BEGIN
  1430.                         BlockMove(Ptr(originalText^), @originalStr, length(originalText^^) + 1);
  1431.                         SetIText(item, originalStr);
  1432.                         END;
  1433.                     waitTicks := 6 * 60;
  1434.                     END;
  1435.                 END;
  1436.     END;
  1437.  
  1438.     { Forward on to the standard filter }
  1439.     IF gMacAppAlertFilter <> NIL THEN
  1440.         DoShowAboutAppFilter := CallAlertFilter(theDialog, theEvent, itemHit, gMacAppAlertFilter);
  1441.  
  1442.     END;
  1443.  
  1444. PROCEDURE TApplication.DoShowAboutApp;
  1445. { Method to display the "About" box for your application.  Override to do interesting things.
  1446. Since it is normally called from a command; the app usually has the maximum free space available. }
  1447.  
  1448.     VAR
  1449.         apName:             Str255;
  1450.         apRefnum:            integer;
  1451.         apParam:            Handle;
  1452.  
  1453.     BEGIN
  1454.     FailSpaceIsLow;
  1455.     GetAppParms(apName, apRefnum, apParam);
  1456.     ParamText(apName, '', '', '');                        { Put Application name in the about box }
  1457.     hadCreditsStringList := (GetResource('STR#', kDefaultCredits) <> NIL);
  1458.     IF hadCreditsStringList THEN
  1459.         BEGIN
  1460.         lastCreditsStringIndex := 1;
  1461.         lastCreditsShownTicks := TickCount;
  1462.         waitTicks := 5 * 60;
  1463.         originalText := NewString('');
  1464.         IF MacAppAlert(phAboutApp, @DoShowAboutAppFilter) <> 0 THEN;
  1465.         Handle(originalText) := DisposeIfHandle(originalText);
  1466.         END
  1467.     ELSE
  1468.         StdAlert(phAboutApp);
  1469.     END;
  1470.  
  1471. {--------------------------------------------------------------------------------------------------}
  1472. {$S MAApplicationRes}
  1473.  
  1474. PROCEDURE TApplication.EachFreeWindow(PROCEDURE DoToWindow(aWindow: TWindow));
  1475.  
  1476.     BEGIN
  1477.     gFreeWindowList.Each(DoToWindow);
  1478.     END;
  1479.  
  1480. {--------------------------------------------------------------------------------------------------}
  1481. {$S MAFields}
  1482.  
  1483. PROCEDURE TApplication.Fields(PROCEDURE DoToField(fieldName: Str255;
  1484.                                                   fieldAddr: Ptr;
  1485.                                                   fieldType: integer)); OVERRIDE;
  1486.  
  1487.     BEGIN
  1488.     DoToField('TApplication', NIL, bClass);
  1489.     DoToField('fCommandQueue', @fCommandQueue, bObject);
  1490.     DoToField('fLastCommand', @fLastCommand, bObject);
  1491.     DoToField('fLaunchWithNewDocument', @fLaunchWithNewDocument, bBoolean);
  1492.  
  1493.     DoToField('fTicksOfLastIdle', @fTicksOfLastIdle, bLongint);
  1494.     DoToField('fTicksTilNextIdle', @fTicksTilNextIdle, bLongint);
  1495.  
  1496.     DoToField('gAppDone', @gAppDone, bBoolean);
  1497.     DoToField('gApplication', @gApplication, bObject);
  1498.  
  1499.     TextStyleFields('gApplicationStyle', gApplicationStyle, DoToField);
  1500.  
  1501.     {$IFC qDebug}
  1502.     DoToField('gBusyTempRgn', @gBusyTempRgn, bBoolean);
  1503.     {$EndC}
  1504.     DoToField('gChooserOK', @gChooserOK, bBoolean);
  1505.     DoToField('gClickCount', @gClickCount, bInteger);
  1506.     DoToField('gClipClaimed', @gClipClaimed, bBoolean);
  1507.     DoToField('gClipOrphanage', @gClipOrphanage, bObject);
  1508.     DoToField('gClipUndoView', @gClipUndoView, bObject);
  1509.     DoToField('gClipView', @gClipView, bObject);
  1510.     DoToField('gClipWindow', @gClipWindow, bObject);
  1511.     DoToField('gClipWrittenToDeskScrap', @gClipWrittenToDeskScrap, bBoolean);
  1512.  
  1513.     ConfigRecFields('gConfiguration', gConfiguration, DoToField);
  1514.  
  1515.     DoToField('gCouldPrint', @gCouldPrint, bBoolean);
  1516.     DoToField('gCurrPrintHandler', @gCurrPrintHandler, bObject);
  1517.     DoToField('gCursorRgn', @gCursorRgn, bRgnHandle);
  1518.     {$IFC qDebug}
  1519.     DoToField('gDebugPrinting', @gDebugPrinting, bBoolean);
  1520.     {$EndC}
  1521.     DoToField('gDocList', @gDocList, bObject);
  1522.     DoToField('gDrawingPictScrap', @gDrawingPictScrap, bBoolean);
  1523.     DoToField('gDrawingPictScrapView', @gDrawingPictScrapView, bObject);
  1524.     DoToField('gErrorParm3', @gErrorParm3, bString);
  1525.     DoToField('gEventLevel', @gEventLevel, bInteger);
  1526.     {$IFC qDebug}
  1527.     DoToField('gExperimenting', @gExperimenting, bBoolean);
  1528.     {$EndC}
  1529.     DoToField('gFileCount', @gFileCount, bInteger);
  1530.     DoToField('gFinderPrinting', @gFinderPrinting, bBoolean);
  1531.     DoToField('gFocusedView', @gFocusedView, bObject);
  1532.     DoToField('gFreeWindowList', @gFreeWindowList, bObject);
  1533.     DoToField('gGotClipType', @gGotClipType, bBoolean);
  1534.     DoToField('gHeadCohandler', @gHeadCoHandler, bObject);
  1535.     DoToField('gIdlePhase', @gIdlePhase, bByte);
  1536.     DoToField('gInBackground', @gInBackground, bBoolean);
  1537.     DoToField('gInitialized', @gInitialized, bBoolean);
  1538.     {$IFC qDebug}
  1539.     DoToField('gIntenseDebugging', @gIntenseDebugging, bBoolean);
  1540.     {$EndC}
  1541.     DoToField('gLastClickPart', @gLastClickPart, bInteger);
  1542.     DoToField('gLastDeskAcc', @gLastDeskAcc, bLongint);
  1543.     DoToField('gLastMsePt', @gLastMsePt, bPoint);
  1544.     DoToField('gLastUpTime', @gLastUpTime, bLongint);
  1545.     DoToField('gLongOffset', @gLongOffset, bVPoint);
  1546.     DoToField('gLowSpaceInterval', @gLowSpaceInterval, bLongint);
  1547.     DoToField('gMainEventMask', @gMainEventMask, bHexInteger);
  1548.     DoToField('gMainFileType', @gMainFileType, bOSType);
  1549.     DoToField('gMBarDisplayed', @gMBarDisplayed, bInteger);
  1550.     DoToField('gMBarHeight', @gMBarHeight, bInteger);
  1551.     DoToField('gMBarHierarchical', @gMBarHierarchical, bInteger);
  1552.     DoToField('gMBarNotDisplayed', @gMBarNotDisplayed, bInteger);
  1553.     DoToField('gMenusAreSetup', @gMenusAreSetup, bBoolean);
  1554.     ScrapStuffFields('gNewScrapStuff', gNewScrapStuff, DoToField);
  1555.     DoToField('gNextSpaceMsg', @gNextSpaceMsg, bLongint);
  1556.     DoToField('gNoChanges', @gNoChanges, bObject);
  1557.     DoToField('gNullPrintHandler', @gNullPrintHandler, bObject);
  1558.     DoToField('gNumUntitled', @gNumUntitled, bInteger);
  1559.     DoToField('gOldChooserFlag', @gOldChooserFlag, bBoolean);
  1560.     ScrapStuffFields('gOldScrapStuff', gOldScrapStuff, DoToField);
  1561.     DoToField('gOrthogonal[h]', @gOrthogonal[h], bByte);
  1562.     DoToField('gOrthogonal[v]', @gOrthogonal[v], bByte);
  1563.     DoToField('gPageOffset', @gPageOffset, bVPoint);
  1564.     DoToField('gPrefClipType', @gPrefClipType, bOSType);
  1565.     DoToField('gPrintHandler', @gPrintHandler, bObject);
  1566.     DoToField('gPrinting', @gPrinting, bBoolean);
  1567.     DoToField('gRedrawMenuBar', @gRedrawMenuBar, bBoolean);
  1568.     {$IFC qDebug}
  1569.     DoToField('gReportEvt', @gReportEvt, bBoolean);
  1570.     {$EndC}
  1571.     {$IFC qDebug}
  1572.     DoToField('gReportMenuChoices', @gReportMenuChoices, bBoolean);
  1573.     {$EndC}
  1574.     {$IFC qDebug}
  1575.     DoToField('gRsrcCheck', @gRsrcCheck, bBoolean);
  1576.     {$EndC}
  1577.     DoToField('gSaveFocusRec', NIL, bTitle);
  1578.     DoToField('  isValid', @gSaveFocusRec.isValid, bBoolean);
  1579.     DoToField('  clip', @gSaveFocusRec.clip, bRgnHandle);
  1580.     DoToField('  drawingPictScrap', @gSaveFocusRec.drawingPictScrap, bBoolean);
  1581.     DoToField('  drawingPictScrapView', @gSaveFocusRec.drawingPictScrapView, bObject);
  1582.     DoToField('  focusedView', @gSaveFocusRec.focusedView, bObject);
  1583.     DoToField('  longOffset', @gSaveFocusRec.longOffset, bVPoint);
  1584.     DoToField('  org', @gSaveFocusRec.org, bPoint);
  1585.     DoToField('  port', @gSaveFocusRec.port, bWindowPtr);
  1586.     DoToField('  printing', @gSaveFocusRec.printing, bBoolean);
  1587.     DoToField('gSignatureCount', @gSignatureCount, bInteger);
  1588.     DoToField('gStdHysteresis', @gStdHysteresis, bPoint);
  1589.     DoToField('gStdStaggerCount', @gStdStaggerCount, bInteger);
  1590.     DoToField('gStdWMoveBounds', @gStdWMoveBounds, bRect);
  1591.     DoToField('gStdWSizeRect', @gStdWSizeRect, bRect);
  1592.     DoToField('gStdWScreenRect', @gStdWScreenRect, bRect);
  1593.     DoToField('gSysWindowActive', @gSysWindowActive, bBoolean);
  1594.  
  1595.     TextStyleFields('gSystemStyle', gSystemStyle, DoToField);
  1596.  
  1597.     DoToField('gTarget', @gTarget, bObject);
  1598.     DoToField('gTempRgn', @gTempRgn, bRgnHandle);
  1599.     {$IFC qDebug}
  1600.     DoToField('gTraceIdle', @gTraceIdle, bBoolean);
  1601.     {$EndC}
  1602.     DoToField('gUndoState', @gUndoState, bBoolean);
  1603.     DoToField('gUndoCmd', @gUndoCmd, bInteger);
  1604.     {$IFC qDebug}
  1605.     DoToField('gUsedBy', @gUsedBy, bString);
  1606.     {$EndC}
  1607.     DoToField('gVarClipPicSize', @gVarClipPicSize, bBoolean);
  1608.     DoToField('gWorkPort', @gWorkPort, bGrafPtr);
  1609.     DoToField('gWResSignature', @gWResSignature, bIDType);
  1610.     DoToField('gWResType', @gWResType, bString);
  1611.     DoToField('gZeroPt', @gZeroPt, bPoint);
  1612.     DoToField('gZeroRect', @gZeroRect, bRect);
  1613.     DoToField('gZeroVPt', @gZeroVPt, bVPoint);
  1614.     DoToField('gZeroVRect', @gZeroVRect, bVRect);
  1615.  
  1616.     INHERITED Fields(DoToField);
  1617.     END;
  1618.  
  1619. {--------------------------------------------------------------------------------------------------}
  1620. {$S MAApplicationRes}
  1621.  
  1622. PROCEDURE TApplication.ForAllDocumentsDo(PROCEDURE DoToDoc(aDocument: TDocument));
  1623.  
  1624.     BEGIN
  1625.     gDocList.Each(DoToDoc);
  1626.     END;
  1627.  
  1628. {--------------------------------------------------------------------------------------------------}
  1629. {$S MAApplicationRes}
  1630.  
  1631. PROCEDURE TApplication.ForAllWindowsDo(PROCEDURE DoToWind(aWindow: TWindow));
  1632.  
  1633.     PROCEDURE DoToYourWindows(aDocument: TDocument);
  1634.  
  1635.         BEGIN
  1636.         aDocument.ForAllWindowsDo(DoToWind);
  1637.         END;
  1638.  
  1639.     BEGIN
  1640.     ForAllDocumentsDo(DoToYourWindows);
  1641.     EachFreeWindow(DoToWind);
  1642.     END;
  1643.  
  1644. {--------------------------------------------------------------------------------------------------}
  1645. {$S MAInspector}
  1646.  
  1647. PROCEDURE TApplication.GetInspectorName(VAR inspectorName: Str255);
  1648.  
  1649.     BEGIN
  1650.     IF SELF = gApplication THEN
  1651.         inspectorName := 'gApplication';
  1652.     END;
  1653.  
  1654. {--------------------------------------------------------------------------------------------------}
  1655. {$S MAClipboard}
  1656.  
  1657. FUNCTION TApplication.GetDataToPaste(aDataHandle: Handle;
  1658.                                      VAR dataType: ResType): LONGINT;
  1659.  
  1660.     VAR
  1661.         err:                LONGINT;
  1662.         myType:             ResType;
  1663.  
  1664.     BEGIN
  1665.     IF gGotClipType THEN
  1666.         BEGIN
  1667.         dataType := gPrefClipType;
  1668.  
  1669.         err := gClipView.GivePasteData(aDataHandle, dataType);
  1670.  
  1671.         IF err < 0 THEN
  1672.             Failure(err, 0);
  1673.         END
  1674.     ELSE
  1675.         BEGIN
  1676.         {$IFC qDebug}
  1677.         ProgramBreak('GetDataToPaste called when gGotClipType was FALSE');
  1678.         {$ENDC}
  1679.         END;
  1680.  
  1681.     GetDataToPaste := err;
  1682.     END;
  1683.  
  1684. {--------------------------------------------------------------------------------------------------}
  1685. {$S MAApplicationRes}
  1686.  
  1687. FUNCTION TApplication.GetEvent(eventMask: integer;
  1688.                                sleep: LONGINT;
  1689.                                cursorRgn: RgnHandle;
  1690.                                VAR anEvent: EventRecord): BOOLEAN;
  1691.  
  1692.     CONST
  1693.         kMaxSleep            = 60;                        { max sleep in foreground so MultiFinder
  1694.                                                          gives time to non-desk accessory drivers }
  1695.  
  1696.     VAR
  1697.         haveEvent:            BOOLEAN;
  1698.         {$IFC qPerform}
  1699.         oldSetting:         BOOLEAN;
  1700.         {$ENDC}
  1701.  
  1702.     BEGIN
  1703.  
  1704.     {$IFC qDebug}
  1705.     gRsrcCheck := gRsrcCheck - 1;
  1706.     IF gRsrcCheck <= 0 THEN
  1707.         BEGIN
  1708.         CheckRsrcUsage;
  1709.         gRsrcCheck := kRsrcCheckInterval;
  1710.         END;
  1711.     {$ENDC qDebug}
  1712.  
  1713.     IF qNeedsWaitNextEvent | gConfiguration.hasWaitNextEvent THEN
  1714.         BEGIN
  1715.         {$IFC qDebug}
  1716.         IF gIntenseDebugging & gReportEvt THEN
  1717.             BEGIN
  1718.             WRITE('WaitNextEvent: sleep=', sleep: 0);
  1719.             { faceless driver bug fixed in MF 7.0 }
  1720.             IF (gConfiguration.systemVersion < $700) & NOT gInBackground THEN
  1721.                 WRITE(', MaxSleep=', kMaxSleep: 0);
  1722.  
  1723.             IF cursorRgn = NIL THEN
  1724.                 WRITE(', cursor region=NIL')
  1725.             ELSE
  1726.                 WrLblRect(', cursor', cursorRgn^^.rgnBBox);
  1727.             Writeln;
  1728.             END;
  1729.         {$ENDC}
  1730.         ActivateBusyCursor(FALSE);                        { Turn off busy cursor while we're away.}
  1731.  
  1732.         {$IFC qPerform}
  1733.         oldSetting := DebugPerfMonitor(FALSE);
  1734.         {$ENDC}
  1735.  
  1736.         { faceless driver bug fixed in MF 7.0 }
  1737.         IF (gConfiguration.systemVersion < $700) & NOT gInBackground THEN
  1738.             sleep := Min(sleep, kMaxSleep);
  1739.  
  1740.         haveEvent := WaitNextEvent(eventMask, anEvent, sleep, cursorRgn);
  1741.  
  1742.         {$IFC qPerform}
  1743.         IF DebugPerfMonitor(oldSetting) THEN;
  1744.         {$ENDC}
  1745.  
  1746.         IF NOT gInBackground THEN                        { If we're not in the background, then }
  1747.             ActivateBusyCursor(TRUE);                    { …enable the busy cursor mechanism. }
  1748.         END
  1749.     ELSE
  1750.         BEGIN
  1751.         {$IFC qPerform}
  1752.         oldSetting := DebugPerfMonitor(FALSE);
  1753.         {$ENDC}
  1754.  
  1755.         SystemTask;
  1756.         haveEvent := GetNextEvent(eventMask, anEvent);
  1757.  
  1758.         {$IFC qPerform}
  1759.         IF DebugPerfMonitor(oldSetting) THEN;
  1760.         {$ENDC}
  1761.         END;
  1762.  
  1763.     GetEvent := haveEvent;
  1764.  
  1765.     END;
  1766.  
  1767. {--------------------------------------------------------------------------------------------------}
  1768. {$S MAApplicationRes}
  1769.  
  1770. FUNCTION TApplication.GetFrontWindow: TWindow;
  1771.  
  1772.     PROCEDURE DoToWMgrWindow(theWMgrWindow: WindowPtr);
  1773.  
  1774.         VAR
  1775.             aWindow:            TWindow;
  1776.  
  1777.         BEGIN
  1778.         aWindow := WMgrToWindow(theWMgrWindow);
  1779.         IF (aWindow <> NIL) & aWindow.IsShown & (NOT aWindow.fFloats) THEN
  1780.             BEGIN
  1781.             GetFrontWindow := aWindow;
  1782.             EXIT(GetFrontWindow)
  1783.             END;
  1784.         END;
  1785.  
  1786.     BEGIN
  1787.     GetFrontWindow := NIL;
  1788.     IF NOT IsDeskAccessory(FrontWindow) THEN
  1789.         EachWMgrWindowDo(DoToWMgrWindow);
  1790.     END;
  1791.  
  1792. {--------------------------------------------------------------------------------------------------}
  1793. {$S MAApplicationRes}
  1794.  
  1795. FUNCTION TApplication.GetActiveWindow: TWindow;
  1796.  
  1797.     PROCEDURE DoToWMgrWindow(theWMgrWindow: WindowPtr);
  1798.  
  1799.         VAR
  1800.             aWindow:            TWindow;
  1801.  
  1802.         BEGIN
  1803.         aWindow := WMgrToWindow(theWMgrWindow);
  1804.         IF (aWindow <> NIL) & aWindow.IsShown & aWindow.fIsActive & (NOT aWindow.fFloats) THEN
  1805.             BEGIN
  1806.             GetActiveWindow := aWindow;
  1807.             EXIT(GetActiveWindow)
  1808.             END;
  1809.         END;
  1810.  
  1811.     BEGIN
  1812.     GetActiveWindow := NIL;
  1813.     IF NOT IsDeskAccessory(FrontWindow) THEN
  1814.         EachWMgrWindowDo(DoToWMgrWindow);
  1815.     END;
  1816.  
  1817. {--------------------------------------------------------------------------------------------------}
  1818. {$S MAApplicationRes}
  1819.  
  1820. FUNCTION TApplication.GetLastCommand: TCommand;
  1821.  
  1822.     BEGIN
  1823.     GetLastCommand := fLastCommand;
  1824.     END;
  1825.  
  1826. {--------------------------------------------------------------------------------------------------}
  1827. {$S MAApplicationRes}
  1828.  
  1829. FUNCTION TApplication.GetNextCommand: TCommand;
  1830.  
  1831.     VAR
  1832.         aCommand:            TCommand;
  1833.  
  1834.     FUNCTION IsReadyToGo(command: TCommand): BOOLEAN;
  1835.  
  1836.         BEGIN
  1837.         IsReadyToGo := command.IsReadyToExecute;
  1838.         END;
  1839.  
  1840.     BEGIN
  1841.     IF NOT fCommandQueue.IsEmpty THEN
  1842.         BEGIN
  1843.         aCommand := TCommand(fCommandQueue.FirstThat(IsReadyToGo));
  1844.         IF (aCommand <> NIL) & NOT aCommand.fRecurring THEN
  1845.             fCommandQueue.Delete(aCommand);
  1846.         GetNextCommand := aCommand;
  1847.         END
  1848.     ELSE
  1849.         GetNextCommand := NIL;
  1850.     END;
  1851.  
  1852. {--------------------------------------------------------------------------------------------------}
  1853. {$S MAOpen}
  1854.  { ??? We should not muck with the window template; the extra code isn't worth it
  1855.   since programmer can easily change the resource file ??? }
  1856.  
  1857. FUNCTION TApplication.GetRsrcWindow(storage: Ptr;
  1858.                                     rsrcId: integer;
  1859.                                     VAR isResizable, isClosable: BOOLEAN): WindowPtr;
  1860. { We force INVISIBLE in the WIND definition so the screen won't flash. }
  1861.  
  1862.     TYPE
  1863.         WINDTemplate        = RECORD
  1864.             bounds:             Rect;
  1865.             procID:             integer;
  1866.             visible, filler1:    BOOLEAN;
  1867.             goAway, filler2:    BOOLEAN;
  1868.             refcon:             LONGINT;
  1869.             itemsID:            integer;                { only for DLOG resource }
  1870.             END;
  1871.         WINDTemplatePtr    = ^WINDTemplate;
  1872.         WINDTemplateHandle = ^WINDTemplatePtr;
  1873.  
  1874.     VAR
  1875.         aWMgrWindow:        WindowPtr;
  1876.         templateHandle:     WINDTemplateHandle;
  1877.         rsrcType:            ResType;
  1878.         ditl:                Handle;
  1879.         oldPerm:            BOOLEAN;
  1880.         fi:                 FailInfo;
  1881.  
  1882.     PROCEDURE HdlFailure(error: integer;
  1883.                          message: LONGINT);             { ??? ERROR ??? }
  1884.  
  1885.         BEGIN
  1886.         { Make sure the perm allocation flag is set back to what it was
  1887.           when we entered GetRsrcWindow. }
  1888.         oldPerm := PermAllocation(oldPerm);
  1889.         END;
  1890.  
  1891.     BEGIN
  1892.     oldPerm := PermAllocation(FALSE);
  1893.    { Even though the window is permanent, we allocate it
  1894.  under a temporary flag so that the maximum memory
  1895.  is available. Quickdraw can blow up if it can't
  1896.  allocate a grafPort. }
  1897.  
  1898.     CatchFailures(fi, HdlFailure);
  1899.  
  1900.     templateHandle := WINDTemplateHandle(GetResource('WIND', rsrcId));
  1901.     FailNILResource(templateHandle);
  1902.     MoveHHi(Handle(templateHandle));                    { in case it is locked by the ROM }
  1903.  
  1904.     WITH templateHandle^^ DO
  1905.         BEGIN
  1906.         { ignore request for zoomDocProc if not 128K ROM, because
  1907.         the user might be running pre-3.0 System, which can't
  1908.         handle zoomDocProc }
  1909.         IF NOT qNeedsROM128K & NOT gConfiguration.hasROM128K THEN
  1910.             procID := BAND(procID, $FFF7);
  1911.  
  1912.         visible := FALSE;
  1913.         isClosable := goAway;
  1914.         isResizable := (procID = documentProc) | (procID = zoomDocProc);
  1915.    { If your own defProc is resizable, too, then after
  1916.    the call on GetRsrcWindow, set isResizable TRUE }
  1917.         END;
  1918.  
  1919.     IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  1920.         aWMgrWindow := WindowPtr(GetNewCWindow(rsrcId, Pointer(storage), Pointer( - 1)))
  1921.     ELSE
  1922.         aWMgrWindow := GetNewWindow(rsrcId, Pointer(storage), Pointer( - 1));
  1923.  
  1924.     FailNil(aWMgrWindow);
  1925.     oldPerm := PermAllocation(oldPerm);
  1926.     Success(fi);                                        { Don't need the failure handler since we've
  1927.                                                          set the perm allocation flag back. }
  1928.  
  1929.     { Now we must make sure that the code reserve is still intact.}
  1930.     IF NOT CheckReserve THEN
  1931.         BEGIN
  1932.         aWMgrWindow := FreeIfWMgrWindow(aWMgrWindow, storage = NIL);
  1933.  
  1934.         Failure(memFullErr, 0);
  1935.         END;
  1936.  
  1937.     GetRsrcWindow := aWMgrWindow;
  1938.     END;
  1939.  
  1940. {--------------------------------------------------------------------------------------------------}
  1941. {$S MAApplicationRes}
  1942.  
  1943. FUNCTION TApplication.HandleActivateEvent(VAR theEventInfo: EventInfo): TCommand;
  1944.  
  1945.     VAR
  1946.         aWindow:            TWindow;
  1947.  
  1948.     BEGIN
  1949.     WITH theEventInfo, thePEvent^ DO
  1950.         BEGIN
  1951.         aWindow := WMgrToWindow(WindowPtr(message));
  1952.         IF aWindow <> NIL THEN
  1953.             aWindow.Activate(Odd(modifiers));
  1954.         END;
  1955.  
  1956.     HandleActivateEvent := NIL;
  1957.     END;
  1958.  
  1959. {--------------------------------------------------------------------------------------------------}
  1960. {$S MAApplicationRes}
  1961.  
  1962. FUNCTION TApplication.HandleAlienEvent(VAR theEventInfo: EventInfo): TCommand;
  1963.  
  1964.     VAR
  1965.         aCommand:            TCommand;
  1966.         anEvtHandler:        TEvtHandler;
  1967.  
  1968.     FUNCTION TakeEvent(anEvtHandler: TEvtHandler): BOOLEAN;
  1969.  
  1970.         BEGIN
  1971.         TakeEvent := anEvtHandler.DoHandleEvent(theEventInfo.thePEvent, aCommand);
  1972.         END;
  1973.  
  1974.     BEGIN
  1975.     aCommand := NIL;
  1976.     IF gHeadCoHandler <> NIL THEN
  1977.         anEvtHandler := gHeadCoHandler.FirstHandlerThat(TakeEvent);
  1978.     HandleAlienEvent := aCommand;
  1979.     END;
  1980.  
  1981. {--------------------------------------------------------------------------------------------------}
  1982. {$S MADoCommand}
  1983.  
  1984. FUNCTION TApplication.HandleDiskEvent(VAR theEventInfo: EventInfo): TCommand;
  1985.  
  1986.     CONST
  1987.         topLeft             = $00500070;
  1988.  
  1989.     VAR
  1990.         err:                integer;
  1991.  
  1992.     BEGIN
  1993.     WITH theEventInfo.thePEvent^ DO
  1994.         IF HiWrd(message) <> noErr THEN
  1995.             BEGIN
  1996.             err := DIBadMount(Point(topLeft), message); { ??? do something with the error ??? }
  1997.             {$IFC qDebug}
  1998.             IF err <> noErr THEN
  1999.                 Writeln('error from DIBadMount is ', err: 1);
  2000.             {$ENDC}
  2001.             END;
  2002.  
  2003.     HandleDiskEvent := NIL;
  2004.  
  2005.     END;
  2006.  
  2007. {--------------------------------------------------------------------------------------------------}
  2008. {$S MAApplicationRes}
  2009.  
  2010. PROCEDURE TApplication.HandleEvent(VAR theEvent: EventRecord);
  2011.  
  2012.     VAR
  2013.         fi:                 FailInfo;
  2014.         commandToPerform:    TCommand;
  2015.         theEventInfo:        EventInfo;
  2016.         {$IFC qDebug}
  2017.         aMAName:            MAName;
  2018.         {$ENDC}
  2019.  
  2020.     PROCEDURE HandleFailure(error: OSErr;
  2021.                             message: LONGINT);
  2022.  
  2023.         BEGIN
  2024.         PostHandleEvent(theEventInfo);
  2025.         END;
  2026.  
  2027.     BEGIN
  2028.     {$IFC qDebug}
  2029.     IF gReportEvt THEN
  2030.         ReportEvent(theEvent);
  2031.     {$ENDC}
  2032.  
  2033.     WITH theEventInfo, theEvent DO
  2034.         BEGIN
  2035.         thePEvent := @theEvent;
  2036.         theBtnState := BAND(modifiers, btnState) <> 0;
  2037.         theCmdKey := BAND(modifiers, cmdKey) <> 0;
  2038.         theShiftKey := BAND(modifiers, shiftKey) <> 0;
  2039.         theAlphaLock := BAND(modifiers, alphaLock) <> 0;
  2040.         theOptionKey := BAND(modifiers, optionKey) <> 0;
  2041.         theControlKey := BAND(modifiers, controlKey) <> 0;
  2042.         theAutoKey := what = autoKey;
  2043.         theClickCount := gClickCount;
  2044.         theCharacter := chr(0);                         { Default, we don't know if this is a
  2045.                                                          keystroke yet }
  2046.         theKeyCode := 0;                                { Default, we don't know if this is a
  2047.                                                          keystroke yet }
  2048.         affectsMenus := TRUE;                            { assume going in that this event affects
  2049.                                                          the menus }
  2050.         END;
  2051.  
  2052.     CatchFailures(fi, HandleFailure);
  2053.  
  2054.     DispatchEvent(theEventInfo, commandToPerform);
  2055.  
  2056.     IF (commandToPerform <> NIL) THEN                    { Send the command out to be executed }
  2057.         PostCommand(commandToPerform);
  2058.  
  2059.     Success(fi);
  2060.  
  2061.     PostHandleEvent(theEventInfo);
  2062.  
  2063.     END;
  2064.  
  2065. {--------------------------------------------------------------------------------------------------}
  2066. {$S MAApplicationRes}
  2067.  
  2068. FUNCTION OptionKeyIsDown: BOOLEAN;
  2069.  
  2070.     CONST
  2071.         kOptionKey            = 58;
  2072.  
  2073.     VAR
  2074.         theKeys:            KeyMap;
  2075.  
  2076.     BEGIN
  2077.     GetKeys(theKeys);
  2078.     OptionKeyIsDown := theKeys[kOptionKey];
  2079.     END;
  2080.  
  2081. {--------------------------------------------------------------------------------------------------}
  2082. {$S MAFinder}
  2083.  
  2084. PROCEDURE TApplication.HandleFinderRequest;
  2085.  
  2086.     LABEL 1, 2;
  2087.  
  2088.     VAR
  2089.         i:                    integer;
  2090.         anAppFile:            AppFile;
  2091.         continuePrinting:    BOOLEAN;
  2092.         cmd:                CmdNumber;
  2093.         fi:                 FailInfo;
  2094.         aCommand:            TCommand;
  2095.  
  2096.         { ??? need better error messages here ??? }
  2097.  
  2098.     PROCEDURE HdlORequest(error: OSErr;
  2099.                           message: LONGINT);
  2100.  
  2101.         BEGIN
  2102.         IF error <> noErr THEN
  2103.             BEGIN
  2104.             IF message = 0 THEN
  2105.                 BEGIN
  2106.                 gErrorParm3 := anAppFile.fName;
  2107.                 IF cmd = cFinderPrint THEN
  2108.                     message := msgPrintFailed
  2109.                 ELSE
  2110.                     message := msgOpenFailed;
  2111.                 END;
  2112.             ShowError(error, message);
  2113.             END;
  2114.         GOTO 1;                                         { continue the loop }
  2115.         END;
  2116.  
  2117.     PROCEDURE HdlNRequest(error: OSErr;
  2118.                           message: LONGINT);
  2119.  
  2120.         BEGIN
  2121.         IF error <> noErr THEN
  2122.             ShowError(error, message);                    { PollEvent's error handler not in place yet
  2123.                                                          }
  2124.         GOTO 2;                                         { exit the method }
  2125.         END;
  2126.  
  2127.     BEGIN
  2128.     {$IFC qDebug}
  2129.     IF gExperimenting THEN
  2130.         Writeln('File count: ', gFileCount: 1);
  2131.     {$ENDC}
  2132.  
  2133.     IF gFileCount = 0 THEN
  2134.         BEGIN
  2135.         aCommand := NIL;
  2136.         CatchFailures(fi, HdlNRequest);
  2137.  
  2138.         IF OptionKeyIsDown THEN
  2139.             aCommand := DoMenuCommand(cOpen)
  2140.         ELSE IF fLaunchWithNewDocument THEN
  2141.             aCommand := DoMenuCommand(cFinderNew);
  2142.  
  2143.         IF aCommand <> NIL THEN
  2144.             PostCommand(aCommand);
  2145.         Success(fi);
  2146.  
  2147.         END
  2148.     ELSE                                                { it's an OPEN or PRINT of 1 or more
  2149.                                                          existing files }
  2150.         BEGIN
  2151.         continuePrinting := TRUE;
  2152.  
  2153.         IF gFinderPrinting THEN
  2154.             cmd := cFinderPrint
  2155.         ELSE
  2156.             cmd := cFinderOpen;
  2157.  
  2158.         FOR i := 1 TO gFileCount DO
  2159.             BEGIN
  2160.             CatchFailures(fi, HdlORequest);
  2161.  
  2162.             GetAppFiles(i, anAppFile);
  2163.  
  2164.             IF CanOpenDocument(cmd, anAppFile) THEN
  2165.                 BEGIN
  2166.                 ClrAppFiles(i);
  2167.  
  2168.                 IF gFinderPrinting THEN
  2169.                     BEGIN
  2170.                     IF continuePrinting THEN
  2171.                         continuePrinting := PrintDocument(anAppFile);
  2172.                     END
  2173.                 ELSE
  2174.                     OpenOld(cFinderOpen, anAppFile);
  2175.                 END
  2176.             ELSE
  2177.                 Failure(errNotMyType, 0);
  2178.  
  2179.             Success(fi);
  2180.         1:                                                { continue the loop }
  2181.             END;
  2182.         END;
  2183. 2:                                                        { exit the method }
  2184.     END;
  2185.  
  2186. {--------------------------------------------------------------------------------------------------}
  2187. {$S MAApplicationRes}
  2188.  
  2189. FUNCTION TApplication.HandleKeyDownEvent(VAR theEventInfo: EventInfo): TCommand;
  2190.  
  2191.     BEGIN
  2192.     WITH theEventInfo, thePEvent^ DO
  2193.         BEGIN
  2194.         gTarget.KeyEventToComponents(theEventInfo);     { Find out what keys were _REALLY_ pressed }
  2195.  
  2196.         IF theCmdKey THEN
  2197.             HandleKeyDownEvent := gTarget.DoCommandKey(theCharacter, theEventInfo)
  2198.         ELSE
  2199.             HandleKeyDownEvent := gTarget.DoKeyCommand(theCharacter, theKeyCode, theEventInfo);
  2200.         END;
  2201.     END;
  2202.  
  2203. {--------------------------------------------------------------------------------------------------}
  2204. {$S MAApplicationRes}
  2205.  
  2206. FUNCTION TApplication.HandleMouseDown(VAR theEventInfo: EventInfo): TCommand;
  2207.  
  2208.     VAR
  2209.         doClick:            BOOLEAN;
  2210.         aWindow:            TWindow;
  2211.         aWMgrWindow:        WindowPtr;
  2212.         whereMouseDown:     integer;
  2213.         sysWindowAct:        BOOLEAN;
  2214.         aCommand:            TCommand;
  2215.         theMouse:            Point;
  2216.         theVMouse:            VPoint;
  2217.         hysteresis:         Point;
  2218.  
  2219.     BEGIN
  2220.     HandleMouseDown := NIL;
  2221.  
  2222.     WITH theEventInfo, thePEvent^ DO
  2223.         BEGIN
  2224.         whereMouseDown := FindWindow(where, aWMgrWindow);
  2225.         theClickCount := CountClicks(thePEvent, whereMouseDown);
  2226.  
  2227.         aWindow := WMgrToWindow(aWMgrWindow);
  2228.  
  2229.         IF ((whereMouseDown = inMenuBar) & InModalMenuState) | ((whereMouseDown <> inMenuBar) &
  2230.            InModalState & (aWindow <> GetActiveWindow)) THEN
  2231.             BEGIN
  2232.             Beep(2);
  2233.             EXIT(HandleMouseDown);
  2234.             END;
  2235.  
  2236.         END;
  2237.  
  2238.     IF whereMouseDown <> inContent THEN
  2239.         SetCursor(arrow);
  2240.  
  2241.     WITH theEventInfo, thePEvent^ DO
  2242.         CASE whereMouseDown OF
  2243.             inMenuBar:
  2244.                 BEGIN
  2245.                 SetupTheMenus;                            { gives application a chance to setup
  2246.                                                          individual menu items }
  2247.                 HandleMouseDown := MenuEvent(MenuSelect(where));
  2248.                 END;
  2249.  
  2250.             inSysWindow:
  2251.                 SystemClick(thePEvent^, aWMgrWindow);
  2252.  
  2253.             OTHERWISE
  2254.                     { if a MacApp window was associated with the WindowPtr then let the window object
  2255.                     decide what to do with the mouse click }
  2256.                 IF (aWindow <> NIL) & aWindow.Focus THEN { if we can't focus, we're in trouble }
  2257.                     BEGIN
  2258.                     theMouse := where;
  2259.                     GlobalToLocal(theMouse);
  2260.                     aWindow.QDToViewPt(theMouse, theVMouse);
  2261.                     hysteresis := gStdHysteresis;        { don't want std changed by var }
  2262.                     IF aWindow.HandleMouseDown(theVMouse, theEventInfo, hysteresis, aCommand) &
  2263.                        (aCommand <> NIL) THEN
  2264.                         BEGIN
  2265.                         aCommand.fTracksMouse := TRUE;    {??? someday this won't be forced }
  2266.                         aCommand.fInitialPt := where;    {??? someday this won't be forced }
  2267.                         HandleMouseDown := aCommand;
  2268.                         END;
  2269.                     END
  2270.                 ELSE IF qDebug THEN
  2271.                     BEGIN
  2272.                     IF aWindow <> NIL THEN
  2273.                         ProgramBreak(
  2274.                               'In TApplication.HandleMouseDown: couldn''t focus on a window object!'
  2275.                                      )
  2276.                     ELSE IF gIntenseDebugging THEN
  2277.                         Writeln('Got a mouse event for a non-MacApp, non-system window');
  2278.                     END;
  2279.  
  2280.         END;
  2281.     END;
  2282.  
  2283. {--------------------------------------------------------------------------------------------------}
  2284. {$S MAApplicationRes}
  2285.  
  2286. FUNCTION TApplication.HandleMouseUp(VAR theEventInfo: EventInfo): TCommand;
  2287.  
  2288.     BEGIN
  2289.     { Remember time of last mouse up, in order to detect double clicks }
  2290.     gLastUpTime := theEventInfo.thePEvent^.when;
  2291.     HandleMouseUp := NIL;
  2292.     END;
  2293.  
  2294. {--------------------------------------------------------------------------------------------------}
  2295. {$S MAApplicationRes}
  2296.  
  2297. FUNCTION TApplication.HandleSystemEvent(VAR theEventInfo: EventInfo): TCommand;
  2298.  
  2299.     CONST
  2300.         kOsEvtMessageMask    = $FF000000;
  2301.  
  2302.     VAR
  2303.         switchingIn:        BOOLEAN;
  2304.         convertClipboard:    BOOLEAN;
  2305.         aWindow:            TWindow;
  2306.  
  2307.     BEGIN
  2308.     WITH theEventInfo.thePEvent^ DO
  2309.         CASE BSR(BAND(message, kOsEvtMessageMask), 24) OF
  2310.             kSuspendOrResume:
  2311.                 BEGIN
  2312.                 switchingIn := Odd(message);
  2313.                 convertClipboard := BAND(message, $00000002) <> 0;
  2314.  
  2315.                 IF switchingIn THEN
  2316.                     RegainControl(convertClipboard)
  2317.                 ELSE
  2318.                     AboutToLoseControl(convertClipboard);
  2319.  
  2320.                 IF switchingIn THEN
  2321.                     aWindow := GetFrontWindow
  2322.                 ELSE
  2323.                     aWindow := GetActiveWindow;
  2324.  
  2325.                 IF aWindow <> NIL THEN
  2326.                     aWindow.Activate(switchingIn);
  2327.                 gInBackground := NOT switchingIn;
  2328.                 InvalidateCursorRgn;
  2329.                 END;
  2330.             kMouseMovedMessage:
  2331.                 BEGIN
  2332.                 theEventInfo.affectsMenus := FALSE;     { We don't think mouse tracking usually
  2333.                                                          bothers the menus. }
  2334.                 IF TrackCursor THEN;                    { Recalculate the cursor region. After all
  2335.                                                          that's why we got a mouse moved event }
  2336.                 END;
  2337.             OTHERWISE
  2338.                 IF gIntenseDebugging THEN
  2339.                     Writeln('in TApplication.HandleSystemEvent: got unrecognized event');
  2340.         END;
  2341.  
  2342.     HandleSystemEvent := NIL;
  2343.     END;
  2344.  
  2345. {--------------------------------------------------------------------------------------------------}
  2346. {$S MAApplicationRes}
  2347.  
  2348. FUNCTION TApplication.HandleUpdateEvent(VAR theEventInfo: EventInfo): TCommand;
  2349.  
  2350.     VAR
  2351.         aWindow:            TWindow;
  2352.  
  2353.     BEGIN
  2354.     WITH theEventInfo.thePEvent^ DO
  2355.         BEGIN
  2356.         aWindow := WMgrToWindow(WindowPtr(message));
  2357.         IF aWindow <> NIL THEN
  2358.             aWindow.Update;
  2359.         END;
  2360.     HandleUpdateEvent := NIL;
  2361.     END;
  2362.  
  2363. {--------------------------------------------------------------------------------------------------}
  2364. {$S MADebug}
  2365.  
  2366. PROCEDURE TApplication.IdentifySoftware;
  2367.  
  2368.     BEGIN
  2369.     WRITELN('UMacApp of 14 Feb 90 (Valentine''s Day), Compiled on ', COMPDATE, ' @ ', COMPTIME);
  2370.  
  2371.     IDUObject;
  2372.     {$IFC qDebug}
  2373.     IDUDebug;
  2374.     {$EndC}
  2375.     END;
  2376.  
  2377. {--------------------------------------------------------------------------------------------------}
  2378. {$S MAApplicationRes}
  2379.  
  2380. PROCEDURE TApplication.Idle(phase: IdlePhase);
  2381.  
  2382.     VAR
  2383.         currTick:            LONGINT;
  2384.         fi:                 FailInfo;
  2385.  
  2386.     PROCEDURE HdlIdle(error: OSErr;
  2387.                       message: LONGINT);
  2388.  
  2389.         BEGIN
  2390.         gInhibitNestedHandling := TRUE;                 { Don't want to come back into Idle From
  2391.                                                          alert filters or other strange places }
  2392.  
  2393.         END;
  2394.  
  2395.     PROCEDURE DoIdleAction(anEvtHandler: TEvtHandler);
  2396.  
  2397.         VAR
  2398.             didFree:            BOOLEAN;
  2399.             ticksTilNextIdle:    LONGINT;
  2400.  
  2401.         BEGIN
  2402.       { If this handler needs idling, and enough ticks have elapsed
  2403.        since the last time it was idled, call its DoIdle. (This was not
  2404.        made a TEvtHandler method in order to optimize idling speed.) }
  2405.         WITH anEvtHandler DO
  2406.             BEGIN
  2407.             didFree := FALSE;
  2408.             IF fIdleFreq <> kMaxIdleTime THEN            { Does it idle at all? }
  2409.                 BEGIN
  2410.                 IF (phase <> idleContinue) | (currTick - fLastIdle >= fIdleFreq) THEN
  2411.                     BEGIN
  2412.                     didFree := anEvtHandler.DoIdle(phase);
  2413.                     IF NOT didFree THEN
  2414.                         fLastIdle := currTick;
  2415.                     END;
  2416.                 IF NOT didFree & (fIdleFreq <> kMaxIdleTime) THEN
  2417.                     BEGIN
  2418.                     IF fLastIdle = 0 THEN
  2419.                         ticksTilNextIdle := fIdleFreq
  2420.                     ELSE
  2421.                         ticksTilNextIdle := Max(fLastIdle + fIdleFreq - currTick, 0); { accounts for
  2422.                         overdue }
  2423.                     fTicksTilNextIdle := Min(ticksTilNextIdle, fTicksTilNextIdle); { update the
  2424.                         composite }
  2425.                     END;
  2426.                 END;
  2427.             END;
  2428.         END;
  2429.  
  2430.     BEGIN
  2431.     CatchFailures(fi, HdlIdle);
  2432.  
  2433.     currTick := TickCount;
  2434.  
  2435.     IF phase = idleBegin THEN
  2436.         BEGIN
  2437.         {$IFC qDebug}
  2438.         gWasTrcEnable := TRCEnable(gTraceIdle);         { Trace during idle only if user wants to. }
  2439.         {$ENDC}
  2440.         IF NOT gInFilter & MemSpaceIsLow THEN
  2441.             SpaceIsLow
  2442.         ELSE
  2443.             gNextSpaceMsg := currTick;
  2444.  
  2445.         SetupTheMenus;                                    { To get the menu bar redrawn if necessary.}
  2446.         fTicksTilNextIdle := 0;                         { Force idling event handlers &
  2447.                                                          co-handlers.}
  2448.         END;
  2449.  
  2450.     IF (phase <> idleContinue) | (currTick - fTicksOfLastIdle >= fTicksTilNextIdle) THEN
  2451.         BEGIN
  2452.         fTicksTilNextIdle := kMaxIdleTime;
  2453.         IF gHeadCoHandler <> NIL THEN
  2454.             gHeadCoHandler.EachHandler(DoIdleAction);
  2455.         IF qDebug THEN
  2456.             Assertion(gTarget <> NIL, AtStr('gTarget <> nil'));
  2457.         gTarget.EachHandler(DoIdleAction);
  2458.         fTicksOfLastIdle := currTick;
  2459.         END;
  2460.  
  2461.     { If we have WaitNextEvent then the cursor will be tracked via MouseMoved events. }
  2462.     IF (NOT (qNeedsWaitNextEvent | gConfiguration.hasWaitNextEvent) | gAlwaysTrackCursor) &
  2463.        (phase <> idleEnd) THEN
  2464.         BEGIN
  2465.         IF TrackCursor THEN;                            { Recompute the cursor region if necessary.
  2466.                                                          }
  2467.         END
  2468.         {$IFC qDebug}
  2469.     ELSE IF TRCEnable(gWasTrcEnable) THEN                { restore tracing state at end of idle.}
  2470.     {$ENDC}
  2471.     ;
  2472.     Success(fi);
  2473.     END;
  2474.  
  2475. {--------------------------------------------------------------------------------------------------}
  2476. {$S MAApplicationRes}
  2477.  
  2478. FUNCTION TApplication.InModalState: BOOLEAN;
  2479.  
  2480.     VAR
  2481.         aWindow:            TWindow;
  2482.         aWindowPtr:         WindowPtr;
  2483.  
  2484.     BEGIN
  2485.     aWindowPtr := FrontWindow;
  2486.  
  2487.     { in case the front window is an alert or something }
  2488.  
  2489.     IF (WMgrToWindow(aWindowPtr) = NIL) & (aWindowPtr <> NIL) THEN
  2490.         CASE WindowPeek(aWindowPtr)^.windowKind OF
  2491.             dBoxProc, plainDBox, altDBoxProc:
  2492.                 InModalState := TRUE;
  2493.         END
  2494.     ELSE
  2495.         BEGIN
  2496.         aWindow := GetActiveWindow;
  2497.         InModalState := (aWindow <> NIL) & (aWindow.fIsModal);
  2498.         END;
  2499.     END;
  2500.  
  2501. {--------------------------------------------------------------------------------------------------}
  2502. {$S MAApplicationRes}
  2503.  
  2504. FUNCTION TApplication.InModalMenuState: BOOLEAN;
  2505.  
  2506.     VAR
  2507.         aWindow:            TWindow;
  2508.         aWindowPtr:         WindowPtr;
  2509.  
  2510.     BEGIN
  2511.     aWindowPtr := FrontWindow;
  2512.  
  2513.     { in case the front window is an alert or something }
  2514.  
  2515.     IF (WMgrToWindow(aWindowPtr) = NIL) & (aWindowPtr <> NIL) THEN
  2516.         CASE WindowPeek(aWindowPtr)^.windowKind OF
  2517.             dBoxProc, plainDBox, altDBoxProc:
  2518.                 InModalMenuState := TRUE;
  2519.         END
  2520.     ELSE
  2521.         BEGIN
  2522.         aWindow := GetActiveWindow;
  2523.         InModalMenuState := (aWindow <> NIL) & NOT aWindow.AllowsMenuAccess;
  2524.         END;
  2525.     END;
  2526.  
  2527. {--------------------------------------------------------------------------------------------------}
  2528. {$S MANonRes}
  2529.  
  2530. PROCEDURE TApplication.InstallCohandler(aCohandler: TEvtHandler;
  2531.                                         addIt: BOOLEAN);
  2532.  
  2533.     BEGIN
  2534.     fTicksTilNextIdle := 0;                             { Force idling event handlers &
  2535.                                                          co-handlers.}
  2536.     IF addIt THEN
  2537.         gHeadCoHandler := aCohandler.AddHandler(gHeadCoHandler)
  2538.     ELSE
  2539.         gHeadCoHandler := aCohandler.RemoveHandler(gHeadCoHandler);
  2540.     END;
  2541.  
  2542. {--------------------------------------------------------------------------------------------------}
  2543. {$S MAApplicationRes}
  2544.  
  2545. FUNCTION TApplication.IsDeskAccessory(aWMgrWindow: WindowPtr): BOOLEAN;
  2546.  
  2547.     BEGIN
  2548.     IsDeskAccessory := (aWMgrWindow <> NIL) & (WindowPeek(aWMgrWindow)^.windowKind < 0);
  2549.     END;
  2550.  
  2551. {--------------------------------------------------------------------------------------------------}
  2552. {$S MAApplicationRes}
  2553.  
  2554. PROCEDURE TApplication.InvalidateCursorRgn;
  2555.  
  2556.     BEGIN
  2557.     IF gCursorRgn <> NIL THEN
  2558.         SetEmptyRgn(gCursorRgn);                        { Make sure it gets changed back }
  2559.     END;
  2560.  
  2561. {--------------------------------------------------------------------------------------------------}
  2562. {$S MAApplicationRes}
  2563.  
  2564. PROCEDURE TApplication.InvalidateFocus;
  2565.  
  2566.     BEGIN
  2567.     IF gFocusedView <> NIL THEN
  2568.         gFocusedView.InvalidateFocus;
  2569.     END;
  2570.  
  2571. {--------------------------------------------------------------------------------------------------}
  2572. {$S MAApplicationRes}
  2573.  
  2574. PROCEDURE TApplication.KeyEventToComponents(VAR info: EventInfo);
  2575. { See Tech Note #263 for the reason for this abomination }
  2576.  
  2577.     CONST
  2578.         kMaskModifier        = $FE00;                    { need to strip command key from Modifiers }
  2579.         kMaskASCII1         = $000000FF;                { get key from KeyTrans return }
  2580.         kMaskASCII2         = $00FF0000;                { get key from KeyTrans return }
  2581.         kPeriod             = ord('.');
  2582.         kUpKeyMask            = $0080;
  2583.         kMAsmKeyCache        = 38;                        {!!! Replace with system supplied constant
  2584.                                                         when sys 7.0 headers ship }
  2585.  
  2586.     TYPE
  2587.         { !!! Delete this record for 7.0 only operation.
  2588.         This is really a private record so _DON'T_ use any other fields! }
  2589.         MAExpandMemRec        = RECORD
  2590.             emVersion:            integer;                { version of expanded memory }
  2591.             emSize:             LONGINT;                { length of em }
  2592.             emIntlGlobals:        LONGINT;                { international globals pointer }
  2593.             emKeyDeadState:     LONGINT;                { Key1Trans, Key2Trans dead state }
  2594.             emKeyCache:         Ptr;                    { KCHR keyboard cache }
  2595.             emIntlDef:            LONGINT;                { Reserved for Intl }
  2596.             emFirstKeyboard:    BOOLEAN;                { flag byte }
  2597.             emAlign:            BOOLEAN;                { long-align until we need this storage }
  2598.             emItlCache:            ARRAY [0..3] OF LONGINT; { bytes in cache }
  2599.             emItlNeedUnlock:    BOOLEAN;                { for pack6 }
  2600.             emItlDirectGetIntl: BOOLEAN;                { for pack6 }
  2601.             emFiller:            ARRAY [1..22] OF CHAR;    { Reserved room }
  2602.             END;
  2603.         MAExpandMemRecPtr    = ^MAExpandMemRec;
  2604.         MAExpandMemRecHandle    = ^MAExpandMemRecPtr;
  2605.  
  2606.     VAR
  2607.         keyCodeParameter:    integer;                    { See IM-V pp. 195 }
  2608.         virtualKey:         LONGINT;
  2609.         keyInfo:            LONGINT;
  2610.         theChar:            LONGINT;
  2611.         state:                LONGINT;
  2612.         keyTransTable:        Ptr;
  2613.  
  2614.     BEGIN
  2615.     INHERITED KeyEventToComponents(info);                { Get default translation, if any }
  2616.  
  2617.     IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  2618.         BEGIN
  2619.         WITH info, thePEvent^ DO
  2620.             IF (what = keyDown) | (what = autoKey) THEN
  2621.                 BEGIN
  2622.                 { Now see if the command key is down.  If it is, get the correct ASCII translation
  2623.                 by masking the command key out and re-translating because the command key will mask
  2624.                 the shift modifier. }
  2625.  
  2626.                 IF theCmdKey THEN
  2627.                     BEGIN
  2628.                     { set the upkey bit so KeyTrans doesn't do special deadkey processing }
  2629.                     keyCodeParameter := BOR(BOR(BAND(modifiers, kMaskModifier), theKeyCode), kUpKeyMask);
  2630.  
  2631.                     state := 0;
  2632.  
  2633.                     { Get the correct keytable pointer.  We don't want to grope the system unnecessarily
  2634.                     so use the script managers improvements if they're there. }
  2635.                     IF gConfiguration.systemVersion >= $700 THEN
  2636.                         keyTransTable := Ptr(GetEnvirons(kMAsmKeyCache))
  2637.                     ELSE
  2638.                     { Fake handle.  the lomem address is a pointer to the table }
  2639.                         keyTransTable := Ptr(MAExpandMemRecHandle(ExpandMem)^^.emKeyCache);
  2640.  
  2641.                     keyInfo := KeyTrans(keyTransTable, keyCodeParameter, state);
  2642.  
  2643.                     theCharacter := chr(BAND(keyInfo, kMaskASCII1));
  2644.                     IF theCharacter = chr(0) THEN
  2645.                         theCharacter := chr(BSR(BAND(keyInfo, kMaskASCII2), 16));
  2646.                     END;
  2647.                 END;
  2648.  
  2649.         END;
  2650.     END;
  2651.  
  2652. {--------------------------------------------------------------------------------------------------}
  2653. {$S MAOpen}
  2654.  
  2655. FUNCTION TApplication.KindOfDocument(itsCmdNumber: CmdNumber;
  2656.                                      itsAppFilePtr: AppFilePtr): CmdNumber;
  2657.  
  2658.     BEGIN
  2659.     KindOfDocument := itsCmdNumber;
  2660.     END;
  2661.  
  2662. {--------------------------------------------------------------------------------------------------}
  2663. {$S MAInit}
  2664.  
  2665. PROCEDURE TApplication.LaunchClipboard;
  2666.  
  2667.     BEGIN
  2668.     AbsorbScrapStuff;                                    { Get current scrapCount as a baseline }
  2669.     ReadFromDeskScrap;
  2670.     END;
  2671.  
  2672. {--------------------------------------------------------------------------------------------------}
  2673. {$S MAApplicationRes}                                    { must be in the main segment }
  2674.  
  2675. PROCEDURE TApplication.MainEventLoop;
  2676.  
  2677.     BEGIN
  2678.     gIdlePhase := idleBegin;
  2679.     REPEAT
  2680.         IF gIdlePhase = idleBegin THEN
  2681.             UnloadAllSegments;                            { don't unload segs after idle has begun }
  2682.  
  2683.         { ??? should we
  2684.         (1) unload segs after completing idle but before doing the event?
  2685.         (2) unload segs while processing event during background printing? }
  2686.  
  2687.         PollEvent(kAllowApplicationToSleep);
  2688.     UNTIL gAppDone;                                     { gAppDone is a global BOOLEAN; that we set
  2689.                                                          TRUE when the user chooses 'Quit' }
  2690.     END;
  2691.  
  2692. {--------------------------------------------------------------------------------------------------}
  2693. {$S MAInit}
  2694.  
  2695. FUNCTION TApplication.MakeClipboardWindow: TWindow;
  2696.  
  2697.     VAR
  2698.         aDeskScrapView:     TDeskScrapView;
  2699.  
  2700.     BEGIN
  2701.     IF qTemplateViews THEN
  2702.         MakeClipboardWindow := NewTemplateWindow(kIDClipWindow, NIL)
  2703.     ELSE
  2704.         BEGIN
  2705.         New(aDeskScrapView);
  2706.         FailNil(aDeskScrapView);
  2707.         aDeskScrapView.IDeskScrapView;
  2708.         aDeskScrapView.fIdentifier := KIDClipView;
  2709.         MakeClipboardWindow := NewSimpleWindow(kIDClipWindow, TRUE, TRUE, NIL, aDeskScrapView);
  2710.         END;
  2711.     END;
  2712.  
  2713. {--------------------------------------------------------------------------------------------------}
  2714. {$S MAClipboard}
  2715.  
  2716. FUNCTION TApplication.MakeViewForAlienClipboard: TView;
  2717.  
  2718.     BEGIN
  2719.  { If the application doesn't override this then we just set the
  2720.   clipboard view to the orphanage, which handles TEXT and PICT
  2721.   scraps in a standard way. }
  2722.     MakeViewForAlienClipboard := gClipOrphanage;
  2723.     END;
  2724.  
  2725. {--------------------------------------------------------------------------------------------------}
  2726. {$S MASelCommand}
  2727.  
  2728. FUNCTION TApplication.MenuEvent(menuItem: LONGINT): TCommand;
  2729.  
  2730.     VAR
  2731.         fi:                 FailInfo;
  2732.         cmd:                CmdNumber;
  2733.         deskAccName:        Str255;
  2734.         theMenuNumber:        integer;
  2735.         theItemNumber:        integer;
  2736.  
  2737.     PROCEDURE HdlMenuEvt(error: OSErr;
  2738.                          message: LONGINT);
  2739.  
  2740.         BEGIN
  2741.         IF gSysWindowActive THEN
  2742.             ActivateBusyCursor(FALSE);
  2743.  
  2744.         FailNewMessage(error, message, BuildMessage(cmd, msgCmdErr));
  2745.         END;
  2746.  
  2747.     BEGIN
  2748.     MenuEvent := NIL;
  2749.  
  2750.     theMenuNumber := HiWrd(menuItem);
  2751.     theItemNumber := LoWrd(menuItem);
  2752.  
  2753.     IF theMenuNumber <> 0 THEN
  2754.         BEGIN
  2755.  
  2756.         cmd := CmdFromMenuItem(theMenuNumber, theItemNumber);
  2757.  
  2758.         {$IFC qDebug}
  2759.         IF cmd = cCantUndo THEN
  2760.             BEGIN
  2761.             Writeln('Command number ', cCantUndo: 1, ' is reserved for MacApp.');
  2762.             ProgramBreak('Use of reserved command number.');
  2763.             END;
  2764.  
  2765.         IF gReportMenuChoices & (cmd > 0) THEN
  2766.             Writeln('Menu Choice Command Number = ', cmd: 1);
  2767.         {$ENDC qDebug}
  2768.  
  2769.         IF (cmd < 0) & (theMenuNumber = mApple) THEN
  2770.             BEGIN
  2771.             GetItem(MAGetMenu(mApple), theItemNumber, deskAccName);
  2772.             OpenDeskAccessory(deskAccName);
  2773.             END
  2774.         ELSE IF (cmd < cEditBase) | (cmd > cEditLast) | (NOT SystemEdit(cmd - cEditBase)) THEN
  2775.             BEGIN
  2776.             CatchFailures(fi, HdlMenuEvt);
  2777.  
  2778.             IF gSysWindowActive THEN
  2779.                 ActivateBusyCursor(TRUE);
  2780.  
  2781.             MenuEvent := gTarget.DoMenuCommand(cmd);
  2782.  
  2783.             IF gSysWindowActive THEN
  2784.                 ActivateBusyCursor(FALSE);
  2785.  
  2786.             Success(fi);
  2787.             END;
  2788.         END;
  2789.     END;
  2790.  
  2791. {--------------------------------------------------------------------------------------------------}
  2792. {$S MASelCommand}
  2793.  
  2794. PROCEDURE TApplication.OpenDeskAccessory(deskAccName: Str255);
  2795.  
  2796.     VAR
  2797.         aRefNum:            integer;
  2798.         drvrH:                Handle;
  2799.         theID:                integer;
  2800.         theType:            ResType;
  2801.         theName:            Str255;
  2802.         oldPerm:            BOOLEAN;
  2803.         ourHeap:            BOOLEAN;
  2804.         fi:                 FailInfo;
  2805.         err:                OSErr;
  2806.         savedPort:            GrafPtr;
  2807.  
  2808.     PROCEDURE HdlOpenDeskAcc(error: OSErr;
  2809.                              message: LONGINT);
  2810.  
  2811.         BEGIN
  2812.         IF aRefNum <> 0 THEN
  2813.             CloseDeskAcc(aRefNum);
  2814.  
  2815.         IF message = 0 THEN
  2816.             BEGIN
  2817.             gErrorParm3 := deskAccName;
  2818.             { Get rid of leading null character }
  2819.             IF ord(gErrorParm3[1]) = 0 THEN
  2820.                 Delete(gErrorParm3, 1, 1);
  2821.             END;
  2822.  
  2823.         FailNewMessage(error, message, msgOpenFailed);
  2824.         END;
  2825.  
  2826.     FUNCTION IsOpen(itsID: integer): BOOLEAN;
  2827.  
  2828.         VAR
  2829.             dceHnd:             DCtlhandle;
  2830.  
  2831.         BEGIN
  2832.         IsOpen := FALSE;
  2833.         IF (itsID >= 0) & (itsID < GetUnitNtryCnt) THEN
  2834.             BEGIN
  2835.             dceHnd := GetUTableBase^[itsID];
  2836.             IF (dceHnd <> NIL) & BTst(dceHnd^^.dCtlFlags, 5) THEN
  2837.                 IsOpen := TRUE;
  2838.             END;
  2839.         END;
  2840.  
  2841.     BEGIN
  2842.     CatchFailures(fi, HdlOpenDeskAcc);
  2843.     aRefNum := 0;                                        { Make sure failure handler works. }
  2844.  
  2845.     { Attempt to load the DA into memory.  If 'deskAccName' refers to another app }
  2846.     { rather than a real desk acc, then GetNamedResource returns a faked up handle }
  2847.     { courtesy of MultiFinder™. We open the DA with permanent allocation so as to }
  2848.     { ensure that we don't take space from our code segments.                       }
  2849.  
  2850.     oldPerm := PermAllocation(TRUE);
  2851.     drvrH := GetNamedResource('DRVR', deskAccName);
  2852.     IF PermAllocation(oldPerm) THEN;                    { discard result }
  2853.     FailNILResource(drvrH);                             { Either there wasn't enough memory }
  2854.     { …to load the DA, or something is }
  2855.     { …seriously wrong. }
  2856.  
  2857.     { At this point if we are really opening a DA we know it fits in memory.  }
  2858.  
  2859.     GetResInfo(drvrH, theID, theType, theName);         { If it's a not a real DA then this }
  2860.     { will generate a ResError.   }
  2861.     ourHeap := (HandleZone(drvrH) = ApplicZone) | OptionKeyIsDown;    { Find out which zone it 
  2862.                                                         lives in, or if option key is down. }
  2863.  
  2864.     IF (ResError <> noErr) |                            { If it's a MultiFinder fake DA, }
  2865.        IsOpen(theID) |                                    { …or if the DA is already open, }
  2866.        (NOT ourHeap) THEN                                { …or it's not going in our heap }
  2867.         BEGIN
  2868.         oldPerm := PermAllocation(TRUE);                { In case we guess wrong }
  2869.         GetPort(savedPort);
  2870.         aRefNum := OpenDeskAcc(deskAccName);            { …then go ahead and open it. }
  2871.         SetPort(savedPort);
  2872.         IF PermAllocation(oldPerm) THEN;                { discard result }
  2873.         END
  2874.  
  2875.     ELSE
  2876.  
  2877.         BEGIN
  2878.         { If we get this far, we know we have a real DA and it's going into our     }
  2879.         { heap.  Open it, but them make sure we have enough memory to continue }
  2880.         { running.    }
  2881.  
  2882.         FailSpaceIsLow;                                 { In case we're already low on mem. }
  2883.  
  2884.         oldPerm := PermAllocation(TRUE);                { If the pig wants to wallow }
  2885.         GetPort(savedPort);
  2886.         aRefNum := OpenDeskAcc(deskAccName);            { Use temporary allocation. }
  2887.         SetPort(savedPort);
  2888.         IF PermAllocation(oldPerm) THEN;                { discard result }
  2889.  
  2890.         FailSpaceIsLow;                                 { Fail if not enough memory left. }
  2891.         FailNil(drvrH^);                                { …or if the driver was purged to }
  2892.         { …satisfy a code space requirement.}
  2893.         END;
  2894.  
  2895.     Success(fi);
  2896.  
  2897.     END;
  2898.  
  2899. {--------------------------------------------------------------------------------------------------}
  2900. {$S MAOpen}
  2901.  
  2902. PROCEDURE TApplication.OpenNew(itsCmdNumber: CmdNumber);
  2903.  
  2904.     VAR
  2905.         aDocument:            TDocument;
  2906.         fi:                 FailInfo;
  2907.         newTitle:            Str255;
  2908.         aWindow:            TWindow;
  2909.  
  2910.     PROCEDURE HdlOpenNew(error: integer;
  2911.                          message: LONGINT);
  2912.  
  2913.         BEGIN
  2914.         FreeIfObject(aDocument);
  2915.         aDocument := NIL;
  2916.  
  2917.         FailNewMessage(error, message, msgNewFailed);
  2918.         END;
  2919.  
  2920.     BEGIN
  2921.     aDocument := NIL;
  2922.     CatchFailures(fi, HdlOpenNew);
  2923.  
  2924.     aDocument := DoMakeDocument(KindOfDocument(itsCmdNumber, NIL));
  2925.     aDocument.DoInitialState;
  2926.     aDocument.DoMakeViews(kForDisplay);
  2927.     aDocument.DoMakeWindows;
  2928.  
  2929.     aDocument.UntitledName(newTitle);
  2930.     { For MacApp 1.1, newTitle should be always <> '' }
  2931.     IF newTitle <> '' THEN
  2932.         aDocument.SetTitle(newTitle)
  2933.     ELSE IF (aDocument.fWindowList <> NIL) & (aDocument.fWindowList.GetSize > 0) THEN
  2934.     { Grope, grope, grope }
  2935.         BEGIN                                            { must set fTitle field anyways }
  2936.         aWindow := TWindow(aDocument.fWindowList.First);
  2937.  
  2938.         aWindow.GetTitle(newTitle);
  2939.         Handle(aDocument.fTitle) := DisposeIfHandle(aDocument.fTitle);
  2940.         aDocument.fTitle := NewString(Copy(newTitle, aWindow.fPreDocname, length(newTitle) -
  2941.                                            aWindow.fConstTitle));
  2942.         FailNil(aDocument.fTitle);
  2943.         END;
  2944.  
  2945.     AddDocument(aDocument);
  2946.  
  2947.     FailSpaceIsLow;                                     { Fail if document leaves us with no room }
  2948.  
  2949.     { Don't attempt to show the windows until we're sure we won't fail }
  2950.     aDocument.ShowWindows;
  2951.  
  2952.     Success(fi);
  2953.     END;
  2954.  
  2955. {--------------------------------------------------------------------------------------------------}
  2956. {$S MAOpen}
  2957.  
  2958. PROCEDURE TApplication.OpenOld(itsOpenCmd: CmdNumber;
  2959.                                anAppFile: AppFile);
  2960. { Called for opening a document, given its name }
  2961.  
  2962.     VAR
  2963.         aDocument:            TDocument;
  2964.         otherDoc:            TDocument;
  2965.         oldCodeReserve, oldMemReserve: Size;
  2966.         fi:                 FailInfo;
  2967.  
  2968.     PROCEDURE HdlOpenOld(error: integer;
  2969.                          message: LONGINT);
  2970.  
  2971.         BEGIN
  2972.         FreeIfObject(aDocument);
  2973.         aDocument := NIL;
  2974.  
  2975.         IF message = 0 THEN
  2976.             gErrorParm3 := anAppFile.fName;
  2977.         { Set the reserve back to where it was }
  2978.         SetReserveSize(oldCodeReserve, oldMemReserve);
  2979.         FailNewMessage(error, message, msgOpenFailed);
  2980.         END;
  2981.  
  2982.     BEGIN
  2983.     aDocument := NIL;
  2984.  
  2985.     CatchFailures(fi, HdlOpenOld);
  2986.  
  2987.     { Set reserve down a little to ensure that we can open existing documents }
  2988.     GetReserveSize(oldCodeReserve, oldMemReserve);
  2989.     SetReserveSize(oldCodeReserve, oldMemReserve DIV 2);
  2990.  
  2991.     otherDoc := AlreadyOpen(anAppFile.fName, anAppFile.vRefnum);
  2992.     IF otherDoc <> NIL THEN
  2993.         otherDoc.OpenAgain(itsOpenCmd, aDocument);
  2994.  
  2995.     aDocument := DoMakeDocument(KindOfDocument(itsOpenCmd, @anAppFile));
  2996.  
  2997.     aDocument.ReadFromFile(anAppFile, kForDisplay);
  2998.     aDocument.DoMakeViews(kForDisplay);
  2999.     aDocument.DoMakeWindows;
  3000.  
  3001.     AddDocument(aDocument);
  3002.  
  3003.     FailSpaceIsLow;                                     { Fail if the document leaves us with no
  3004.                                                          memory }
  3005.     { Set the reserve back to where it was }
  3006.     SetReserveSize(oldCodeReserve, oldMemReserve);
  3007.  
  3008.     { Don't attempt to show the windows until we're sure we won't fail }
  3009.     aDocument.ShowWindows;
  3010.  
  3011.     Success(fi);
  3012.     END;
  3013.  
  3014. {--------------------------------------------------------------------------------------------------}
  3015. {$S MAApplicationRes}
  3016.  
  3017. PROCEDURE TApplication.PerformCommand(command: TCommand);
  3018.  
  3019.     VAR
  3020.         fi:                 FailInfo;
  3021.         saveCmd:            BOOLEAN;
  3022.         {$IFC qDebug}
  3023.         aMAName:            MAName;
  3024.         {$ENDC}
  3025.  
  3026.     PROCEDURE HdlDoit(error: integer;
  3027.                       message: LONGINT);
  3028.  
  3029.         VAR
  3030.             aCmdNumber:         integer;
  3031.  
  3032.         BEGIN
  3033.         IF gClipClaimed THEN
  3034.             BEGIN
  3035.             SetClipView(gClipUndoView);
  3036.             gClipUndoView := NIL;
  3037.             { The newly-installed view needs to be freed also }
  3038.             { SwapClipViews;}                            { Get original back there… !!! would be nice
  3039.                                                          but doesn't do right thing yet }
  3040.             END;
  3041.  
  3042.         aCmdNumber := command.fCmdNumber;
  3043.         IF command.fFreeOnCompletion THEN
  3044.             FreeIfObject(command);
  3045.  
  3046.         IF command = fLastCommand THEN
  3047.             fLastCommand := NIL;                        { make sure we clear our reference }
  3048.  
  3049.         FailNewMessage(error, message, BuildMessage(aCmdNumber, msgCmdErr));
  3050.         END;
  3051.  
  3052.     BEGIN
  3053.     IF qDebug & (command = NIL) THEN
  3054.         ProgramBreak('NIL passed to TApplication.PerformCommand')
  3055.     ELSE IF qDebug & (NOT IsObject(command)) THEN        { since it's possible to have passed in a
  3056.                                                          freed undoable command allocated in a
  3057.                                                          global variable (due to pilot error) }
  3058.         BEGIN
  3059.         IF VerboseIsobject(command) THEN;
  3060.         ProgramBreak('bogus object passed to TApplication.PerformCommand');
  3061.         END
  3062.     ELSE
  3063.         BEGIN
  3064.         {$IFC qDebug}
  3065.         IF gIntenseDebugging THEN
  3066.             BEGIN
  3067.             command.GetClassName(aMAName);
  3068.             Writeln('The Command to perform: ', aMAName);
  3069.             PLFlush(output);
  3070.             END;
  3071.         {$ENDC}
  3072.  
  3073.         IF command.fTracksMouse THEN
  3074.             BEGIN
  3075.             {$IFC qDebug}
  3076.             IF gIntenseDebugging THEN
  3077.                 IF (command <> NIL) THEN
  3078.                     BEGIN
  3079.                     command.GetClassName(aMAName);
  3080.                     Writeln('Tracking Command: ', aMAName);
  3081.                     PLFlush(output);
  3082.                     END;
  3083.             {$ENDC}
  3084.             IF gEventLevel = 1 THEN                     { Don't unload segs if in nested event
  3085.                                                          handling }
  3086.                 UnloadAllSegments;
  3087.  
  3088.             command := TrackMouse(command.fInitialPt, gStdHysteresis, command);
  3089.             END;
  3090.  
  3091.         IF (command <> NIL) THEN
  3092.             BEGIN
  3093.  
  3094.             saveCmd := command.fCausesChange | command.fCanUndo;
  3095.  
  3096.             IF saveCmd THEN
  3097.                 BEGIN
  3098.                 CommitLastCommand;                        { it frees fLastCommand. If the last
  3099.                                                          (fCausesChange or fCanUndo) command sets
  3100.                                                          fFreeOnCompletion to FALSE then we can
  3101.                                                          execute the same undoable command any
  3102.                                                          number of times. Non-Undoable commands
  3103.                                                          don't get FREEd here but immediately after
  3104.                                                          they're executed (that's performed… not
  3105.                                                          shot) }
  3106.  
  3107.                 IF qDebug & NOT IsObject(command) THEN
  3108.                     BEGIN
  3109.                     IF VerboseIsobject(command) THEN;
  3110.                     ProgramBreak('You may not want to continue with a command that''s been _FREED_!'
  3111.                                  );
  3112.                     END;
  3113.                 END;
  3114.  
  3115.             CatchFailures(fi, HdlDoit);
  3116.             IF gEventLevel = 1 THEN                     { Don't unload segs if in nested event
  3117.                                                          handling }
  3118.                 UnloadAllSegments;
  3119.  
  3120.             gClipClaimed := FALSE;
  3121.  
  3122.             command.DoIt;
  3123.             Success(fi);
  3124.  
  3125.             IF saveCmd THEN
  3126.                 BEGIN
  3127.                 fLastCommand := command;
  3128.                 command.fCmdDone := TRUE;
  3129.                 END;
  3130.  
  3131.             WITH command DO
  3132.                 IF fCausesChange THEN                    { put this after .DoIt, so .DoIt can change
  3133.                                                          this flag }
  3134.                     BEGIN
  3135.                     IF fChangedDocument <> NIL THEN
  3136.                         WITH fChangedDocument DO
  3137.                             SetChangeCount(Max(GetChangeCount + 1, 1)); { protect from rollover (it
  3138.                                                                          goes negative). If your
  3139.                                                                          document has this many
  3140.                                                                          changes (over 2 billion
  3141.                                                                          you are truly sick!}
  3142.                     END;
  3143.  
  3144.             IF NOT saveCmd & command.fFreeOnCompletion THEN
  3145.                 FreeIfObject(command);
  3146.             END;
  3147.         END;
  3148.     END;
  3149.  
  3150. {--------------------------------------------------------------------------------------------------}
  3151. {$S MAApplicationRes}
  3152.  
  3153. PROCEDURE TApplication.PollEvent(allowApplicationToSleep: BOOLEAN);
  3154.  
  3155.     LABEL 1000;
  3156.  
  3157.     VAR
  3158.         fi:                 FailInfo;
  3159.         theEvent:            EventRecord;
  3160.         aWindow:            TWindow;
  3161.         commandToPerform:    TCommand;
  3162.         waitTicks:            LONGINT;
  3163.         idledBeforeEventCall: BOOLEAN;
  3164.  
  3165.     PROCEDURE HdlPollEvt(error: integer;
  3166.                          message: LONGINT);
  3167.  
  3168.         BEGIN
  3169.         {$IFC qDebug}
  3170.         Writeln;                                        { add a blank line after all the messages
  3171.                                                          from Failure }
  3172.         {$ENDC}
  3173.         gEventLevel := gEventLevel - 1;
  3174.         IF gEventLevel = 0 THEN
  3175.             BEGIN
  3176.             IF error <> noErr THEN
  3177.                 BEGIN
  3178.                 UnloadAllSegments;
  3179.                 ShowError(error, message);
  3180.                 END;
  3181.  
  3182.             HiliteMenu(0);                                { Make sure menus get straightened out. }
  3183.             InvalidateMenus;
  3184.  
  3185.             GOTO 1000;                                    { Keep the application running. }
  3186.             END;
  3187.         END;
  3188.  
  3189.     BEGIN
  3190.     gEventLevel := gEventLevel + 1;
  3191.  
  3192.     {$IFC qDebug}
  3193.     IF gTarget = NIL THEN
  3194.         Writeln('Serious Error!!! in TApplication.PollEvent: target = NIL');
  3195.     {$ENDC}
  3196.  
  3197.     CatchFailures(fi, HdlPollEvt);
  3198.  
  3199.     { IF we have any queued commands that have not otherwise been taken care of, now is the time. }
  3200.  
  3201.     commandToPerform := GetNextCommand;
  3202.     IF commandToPerform <> NIL THEN
  3203.         PerformCommand(commandToPerform)
  3204.     ELSE
  3205.         BEGIN
  3206.         { If we're running with WaitNextEvent then if there are no events pending we should
  3207.         idle before calling WaitNextEvent.    This is because we may not come back from WaitNextEvent
  3208.         for an indeterminate period of time.  By idling we make sure the menu bar is correct and
  3209.         give the app a chance to reset the idle frequency and cursor region.}
  3210.  
  3211.         IF (qNeedsWaitNextEvent | gConfiguration.hasWaitNextEvent) & (allowApplicationToSleep &
  3212.            (fTicksTilNextIdle > 0)) & (NOT EventAvail(gMainEventMask, theEvent)) & (gIdlePhase =
  3213.            idleBegin) THEN
  3214.             BEGIN
  3215.             Idle(gIdlePhase);
  3216.             gIdlePhase := idleContinue;
  3217.             idledBeforeEventCall := TRUE;
  3218.             END
  3219.         ELSE
  3220.             idledBeforeEventCall := FALSE;
  3221.  
  3222.         { If the cursor region is invalid, force it's recalculation before going to WNE. It won't be
  3223.         calculated from idle in the WNE case unless gAlwaysTrackCursor is true. }
  3224.         IF (qNeedsWaitNextEvent | gConfiguration.hasWaitNextEvent) & (EmptyRgn(gCursorRgn)) THEN
  3225.             BEGIN
  3226.             IF TrackCursor THEN;
  3227.             END;
  3228.  
  3229.         IF allowApplicationToSleep THEN
  3230.             waitTicks := fTicksTilNextIdle
  3231.         ELSE
  3232.             waitTicks := 0;
  3233.  
  3234.         HiliteMenu(0);
  3235.  
  3236.         IF GetEvent(gMainEventMask, waitTicks, gCursorRgn, theEvent) THEN
  3237.             BEGIN
  3238.             IF gIdlePhase <> idleBegin THEN
  3239.                 BEGIN
  3240.                 Idle(idleEnd);
  3241.                 gIdlePhase := idleBegin;
  3242.                 END;
  3243.             HandleEvent(theEvent);
  3244.             {$IFC qDebug}
  3245.             gErrorParm3 := '?????';                     { to prevent anyone from using old values }
  3246.             {$ENDC}
  3247.             END
  3248.  
  3249.         ELSE IF NOT idledBeforeEventCall | (fTicksTilNextIdle = 0) THEN { idle if we Neeeed to! }
  3250.             BEGIN
  3251.             Idle(gIdlePhase);
  3252.             gIdlePhase := idleContinue;
  3253.             END;
  3254.         END;
  3255.  
  3256.  { The desk scrap may have been changed by use of Cmd-X or Cmd-C in
  3257.   desk accessories. }
  3258.     IF gSysWindowActive THEN
  3259.         BEGIN
  3260.         CheckDeskScrap;
  3261.         InvalidateFocus;
  3262.         END;
  3263.  
  3264.     Success(fi);
  3265.     gEventLevel := gEventLevel - 1;
  3266.  
  3267.     IF gEventLevel = 0 THEN
  3268.         gInhibitNestedHandling := FALSE;                { All clear }
  3269.  
  3270. 1000:                                                    { Failure re-entry point }
  3271.     END;
  3272.  
  3273. {--------------------------------------------------------------------------------------------------}
  3274. {$S MAApplicationRes}
  3275.  
  3276. PROCEDURE TApplication.PostCommand(command: TCommand);
  3277.  
  3278.     BEGIN
  3279.     fCommandQueue.Insert(command);                        { inserts command ordered the list }
  3280.     END;
  3281.  
  3282. {--------------------------------------------------------------------------------------------------}
  3283. {$S MAApplicationRes}
  3284.  
  3285. PROCEDURE TApplication.PostHandleEvent(VAR theEventInfo: EventInfo);
  3286.  
  3287.     VAR
  3288.         sysWindowAct:        BOOLEAN;
  3289.         perm:                BOOLEAN;
  3290.  
  3291.     BEGIN
  3292.     IF theEventInfo.affectsMenus THEN
  3293.         InvalidateMenus;
  3294.  
  3295.     perm := PermAllocation(FALSE);
  3296.     {$IFC qDebug}
  3297.     IF perm THEN
  3298.         ProgramBreak('The permanent flag was left TRUE.');
  3299.     {$ENDC}
  3300.  
  3301.     { See if a system window has been activated or deactivated. }
  3302.     sysWindowAct := IsDeskAccessory(FrontWindow);
  3303.  
  3304.     IF sysWindowAct <> gSysWindowActive THEN
  3305.         BEGIN
  3306.         gSysWindowActive := sysWindowAct;
  3307.  
  3308.         IF gSysWindowActive THEN                        { deactivating to sys window }
  3309.             BEGIN
  3310.             AboutToLoseControl(TRUE);
  3311.             InvalidateMenuBar;
  3312.             END
  3313.         ELSE                                            { coming back from sys window }
  3314.             RegainControl(TRUE);
  3315.         END;
  3316.  
  3317.     END;
  3318.  
  3319. {--------------------------------------------------------------------------------------------------}
  3320. {$S MAFinder}
  3321.  
  3322. FUNCTION TApplication.PrintDocument(anAppFile: AppFile): BOOLEAN;
  3323.  
  3324.     VAR
  3325.         aDocument:            TDocument;
  3326.         aPrintHandler:        TPrintHandler;
  3327.         proceed:            BOOLEAN;
  3328.         fi:                 FailInfo;
  3329.  
  3330.     PROCEDURE HdlPrintDoc(error: integer;
  3331.                           message: LONGINT);
  3332.  
  3333.         BEGIN
  3334.         FreeIfObject(aDocument);
  3335.         aDocument := NIL;
  3336.         END;
  3337.  
  3338.     BEGIN
  3339.     aDocument := NIL;
  3340.     CatchFailures(fi, HdlPrintDoc);
  3341.  
  3342.     aDocument := DoMakeDocument(KindOfDocument(cFinderPrint, @anAppFile));
  3343.     aDocument.ReadFromFile(anAppFile, kForPrinting);
  3344.     aDocument.DoMakeViews(kForPrinting);
  3345.  
  3346.     { Note that if we are finder printing, this segment will be resident }
  3347.     UnloadAllSegments;
  3348.  
  3349.     aPrintHandler := aDocument.fDocPrintHandler;
  3350.     IF aPrintHandler <> NIL THEN
  3351.         BEGIN
  3352.         proceed := aPrintHandler.SetupForFinder;
  3353.         IF proceed & (aPrintHandler.Print(cFinderPrint, proceed) <> NIL) THEN
  3354.         {$IFC qDebug}
  3355.             ProgramBreak('TApplication.PrintDocument: Print return a real command.')
  3356.             {$ENDC} ;
  3357.         END
  3358.     ELSE
  3359.         BEGIN
  3360.         proceed := TRUE;                                { might as well try the next one }
  3361.         {$IFC qDebug}
  3362.         ProgramBreak('TApplication.PrintDocument: The document’s fDocPrintHandler is NIL.');
  3363.         {$ENDC}
  3364.         END;
  3365.  
  3366.     UnloadAllSegments;
  3367.     Success(fi);
  3368.  
  3369.     FreeIfObject(aDocument);
  3370.     aDocument := NIL;
  3371.  
  3372.     UnloadAllSegments;
  3373.     PrintDocument := proceed;
  3374.     END;
  3375.  
  3376. {--------------------------------------------------------------------------------------------------}
  3377. {$S MAClipboard}
  3378.  
  3379. PROCEDURE TApplication.ReadFromDeskScrap;
  3380.  
  3381.     LABEL 1000;
  3382.  
  3383.     VAR
  3384.         aViewForClipboard:    TView;
  3385.         fi:                 FailInfo;
  3386.  
  3387.     PROCEDURE HdlMakeViewForAlienClipbd(error: OSErr;
  3388.                                         message: LONGINT);
  3389.  
  3390.         BEGIN
  3391.  
  3392.         aViewForClipboard := gClipOrphanage;
  3393.         IF message = 0 THEN
  3394.             message := msgImportClipFailed;
  3395.         ShowError(error, message);
  3396.         GOTO 1000;
  3397.         END;
  3398.  
  3399.     BEGIN
  3400.     CatchFailures(fi, HdlMakeViewForAlienClipbd);
  3401.     aViewForClipboard := MakeViewForAlienClipboard;
  3402.     FailNil(aViewForClipboard);
  3403.     Success(fi);
  3404. 1000:
  3405.     ClaimClipboard(aViewForClipboard);
  3406.     END;
  3407.  
  3408. {--------------------------------------------------------------------------------------------------}
  3409. {$S MAApplicationRes}
  3410.  
  3411. PROCEDURE TApplication.RegainControl(checkClipboard: BOOLEAN);
  3412.  
  3413.     BEGIN
  3414.     ActivateBusyCursor(TRUE);
  3415.     IF checkClipboard THEN
  3416.         CheckDeskScrap;
  3417.     END;
  3418.  
  3419. {--------------------------------------------------------------------------------------------------}
  3420. {$S MADebug}
  3421. { Debugging procedure: given an EventRecord, prints out information about the event. }
  3422.  
  3423. PROCEDURE TApplication.ReportEvent(VAR theEvent: EventRecord);
  3424.  
  3425.     VAR
  3426.         ch:                 integer;
  3427.         cap:                integer;
  3428.         aString:            Str255;
  3429.         mods:                STRING[10];
  3430.         aWMgrWindow:        WindowPtr;
  3431.  
  3432.     BEGIN
  3433.     WITH theEvent DO
  3434.         BEGIN
  3435.         WRITE('t = ', when);
  3436.         mods := '          ';
  3437.         { 1234567890 } ;
  3438.  
  3439.         IF BAND(modifiers, controlKey) <> 0 THEN
  3440.             mods[2] := 'C';
  3441.         IF BAND(modifiers, optionKey) <> 0 THEN
  3442.             mods[3] := 'O';
  3443.         IF BAND(modifiers, alphaLock) <> 0 THEN
  3444.             mods[4] := 'L';
  3445.         IF BAND(modifiers, shiftKey) <> 0 THEN
  3446.             mods[5] := 'S';
  3447.         IF BAND(modifiers, cmdKey) <> 0 THEN
  3448.             mods[6] := 'C';
  3449.         IF BAND(modifiers, btnState) <> 0 THEN
  3450.             mods[7] := 'M';
  3451.         IF what = activateEvt THEN
  3452.             IF BAND(modifiers, activeFlag) <> 0 THEN
  3453.                 mods[8] := 'A'
  3454.             ELSE
  3455.                 mods[8] := 'D';
  3456.         WRITE(mods);
  3457.  
  3458.         CASE what OF
  3459.             nullEvent:
  3460.                 Writeln('nullEvent   ');
  3461.             mouseDown, mouseUp:
  3462.                 BEGIN
  3463.                 IF what = mouseDown THEN
  3464.                     WRITE('mouseDown   ')
  3465.                 ELSE
  3466.                     WRITE('mouseUp     ');
  3467.                 WRITE('@ (', where.h: 1, ', ', where.v: 1, ')');
  3468.                 CASE FindWindow(where, aWMgrWindow) OF
  3469.                     inMenuBar:
  3470.                         aString := 'inMenuBar';
  3471.                     inSysWindow:
  3472.                         aString := 'inSysWindow';
  3473.                     inDrag:
  3474.                         aString := 'inDrag';
  3475.                     inGrow:
  3476.                         aString := 'inGrow';
  3477.                     inGoAway:
  3478.                         aString := 'inGoAway';
  3479.                     inContent:
  3480.                         aString := 'inContent';
  3481.                     inZoomIn:
  3482.                         aString := 'inZoomIn';
  3483.                     inZoomOut:
  3484.                         aString := 'inZoomOut';
  3485.                     OTHERWISE
  3486.                         aString := 'Mouse clicked in an unknown place.'
  3487.                 END;
  3488.                 Writeln(' ': 5, aString);
  3489.                 END;
  3490.             keyDown, autoKey, keyUp:
  3491.                 BEGIN
  3492.                 IF what = keyDown THEN
  3493.                     WRITE('keyDown     ')
  3494.                 ELSE IF what = autoKey THEN
  3495.                     WRITE('autoKey     ')
  3496.                 ELSE
  3497.                     WRITE('keyUp       ');
  3498.  
  3499.                 ch := BAND(message, charCodeMask);
  3500.                 cap := BSR(message, 8);
  3501.  
  3502.                 IF (ch >= $20) & (ch <= $D8) & (ch <> $7F) THEN
  3503.                     WRITE('"', chr(ch), '"')
  3504.                 ELSE
  3505.                     WRITE('   ');
  3506.  
  3507.                 Writeln('(', ch: 1, '/', cap: 1, ')');
  3508.                 END;
  3509.             updateEvt, activateEvt:
  3510.                 BEGIN
  3511.                 IF what = updateEvt THEN
  3512.                     WRITE('updateEvt   ')
  3513.                 ELSE
  3514.                     WRITE('activateEvt ');
  3515.  
  3516.                 aString := WindowPeek(message)^.titleHandle^^;
  3517.                 Writeln('"', aString, '"');
  3518.                 END;
  3519.             diskEvt:
  3520.                 Writeln('diskEvt     ', 'd = ', LoWord(message): 1, ' e = ', HiWord(message): 1);
  3521.             networkEvt:
  3522.                 BEGIN
  3523.                 WRITE('networkEvt  ');
  3524.                 WritePtr(message);
  3525.                 Writeln;
  3526.                 END;
  3527.             driverEvt:
  3528.                 BEGIN
  3529.                 WrLblHexLongInt('driverEvt   , message', message);
  3530.                 Writeln;
  3531.                 END;
  3532.             app1Evt:
  3533.                 BEGIN
  3534.                 WrLblHexLongInt('app1Evt     , message', message);
  3535.                 Writeln;
  3536.                 END;
  3537.             app2Evt:
  3538.                 BEGIN
  3539.                 WrLblHexLongInt('app2Evt     , message', message);
  3540.                 Writeln;
  3541.                 END;
  3542.             app3Evt:
  3543.                 BEGIN
  3544.                 WrLblHexLongInt('app3Evt     , message', message);
  3545.                 Writeln;
  3546.                 END;
  3547.             app4Evt:
  3548.                 BEGIN
  3549.                 CASE BSR(BAND(message, $FF000000), 24) OF
  3550.                     kSuspendOrResume:
  3551.                         IF Odd(message) THEN
  3552.                             WRITE('resume      ')
  3553.                         ELSE
  3554.                             WRITE('suspend     ');
  3555.                     kMouseMovedMessage:
  3556.                         WRITE('mouse moved ');
  3557.                     OTHERWISE
  3558.                         WRITE('app4Evt     ');
  3559.                 END;
  3560.                 WrLblHexLongInt(', message', message);
  3561.                 Writeln;
  3562.                 END;
  3563.             OTHERWISE
  3564.                 BEGIN
  3565.                 Writeln('??? unknown = ', what: 1, '   ');
  3566.                 WriteHexLongInt(message);
  3567.                 END;
  3568.         END;
  3569.         END;
  3570.     END;
  3571.  
  3572. {--------------------------------------------------------------------------------------------------}
  3573. {$S MAApplicationRes}                                    { must be in the main segment }
  3574.  
  3575. PROCEDURE TApplication.Run;
  3576.  
  3577.     VAR
  3578.         findSeg:            integer;
  3579.  
  3580.     BEGIN
  3581.     UnloadAllSegments;
  3582.     FailSpaceIsLow;                                     { make sure we have enough memory to
  3583.                                                          continue }
  3584.     gInitialized := TRUE;                                { was set FALSE in InitToolBox }
  3585.  
  3586.     IF gFinderPrinting THEN
  3587.         BEGIN
  3588.         findSeg := GetSegNumber(@FinderSegProc);
  3589.  
  3590.         UnloadAllSegments;
  3591.         SetResidentSegment(findSeg, TRUE);
  3592.  
  3593.         HandleFinderRequest;
  3594.  
  3595.         SetResidentSegment(findSeg, FALSE);
  3596.         UnloadAllSegments;
  3597.  
  3598.         gEventLevel := 0;                                { Indicate outermost level }
  3599.         Close;                                            { Close is always called when quitting app }
  3600.         END
  3601.     ELSE
  3602.         BEGIN
  3603.         LaunchClipboard;
  3604.  
  3605.         UnloadAllSegments;
  3606.         HandleFinderRequest;
  3607.  
  3608.         UnloadAllSegments;
  3609.         gEventLevel := 0;                                { Indicate outermost level }
  3610.         MainEventLoop;
  3611.  
  3612.         AboutToLoseControl(TRUE);
  3613.         END;
  3614.  
  3615.     {$IFC qDebug}
  3616.     { See if previous max. resource usage has been exceeded by the termi-
  3617.     nation code and resources. }
  3618.     CheckRsrcUsage;
  3619.     {$ENDC}
  3620.  
  3621.     { We must call CleanupMacApp here; if we wait to fall thru to the end of the
  3622.     main program, A5 has been invalidated and we can't refer to any globals. }
  3623.     CleanupMacApp;
  3624.     END;
  3625.  
  3626. {--------------------------------------------------------------------------------------------------}
  3627. {$S MAApplicationRes}
  3628.  
  3629. PROCEDURE TApplication.SelectWMgrWindow(aWMgrWindow: WindowPtr);
  3630.  
  3631.     BEGIN
  3632.     SelectWindow(aWMgrWindow);                            { Simply call the toolbox to select it. }
  3633.     gLastClickPart := inDesk;                            { Make sure previous mouse clicks are not }
  3634.     { are not considered part of a multi-click. }
  3635.     END;
  3636.  
  3637. {--------------------------------------------------------------------------------------------------}
  3638. {$S MAClipboard}
  3639.  
  3640. PROCEDURE TApplication.SetClipView(clipView: TView);
  3641.  
  3642.     VAR
  3643.         theSuperView:        TView;
  3644.  
  3645.     PROCEDURE RemoveView(aView: TView);
  3646.  
  3647.         BEGIN
  3648.         theSuperView.RemoveSubView(aView);
  3649.         END;
  3650.  
  3651.     BEGIN
  3652.     IF gClipWindow <> NIL THEN
  3653.         BEGIN
  3654.         IF gClipWindow.CountSubViews > 0 THEN
  3655.             theSuperView := TView(gClipWindow.fSubViews.First)
  3656.         ELSE
  3657.             theSuperView := gClipWindow;
  3658.         theSuperView.EachSubView(RemoveView);
  3659.         theSuperView.AddSubView(clipView);
  3660.         clipView.fSuperView := theSuperView;
  3661.         clipView.SuperViewChangedSize(gZeroVPt, kDontInvalidate);
  3662.         clipView.RevealTop(kDontRedraw);
  3663.         gClipWindow.ForceRedraw;
  3664.         gClipWindow.SetTarget(gClipWindow);
  3665.         gClipWrittenToDeskScrap := clipView = gClipOrphanage;
  3666.         END
  3667.     ELSE
  3668.         BEGIN
  3669.         {$IFC qDebug}
  3670.         ProgramBreak('SetClipView in absence of gClipWindow');
  3671.         {$ENDC}
  3672.         END;
  3673.  
  3674.     clipView.ViewEnable(FALSE, kDontRedraw);            {Ignore clicks while in clipboard views}
  3675.     gClipView := clipView;
  3676.     END;
  3677.  
  3678. {--------------------------------------------------------------------------------------------------}
  3679. {$S MAApplicationRes}
  3680.  
  3681. PROCEDURE TApplication.SetTarget(newTarget: TEvtHandler);
  3682.  
  3683.     BEGIN
  3684.     {$Ifc qDebug}
  3685.     IF newTarget = NIL THEN
  3686.         ProgramBreak('In TApplication.SetTarget…  you''re setting the global target to nil!');
  3687.     {$Endc}
  3688.     IF newTarget <> gTarget THEN
  3689.         BEGIN
  3690.         gTarget.InstallSelection(TRUE, FALSE);
  3691.         newTarget.InstallSelection(FALSE, TRUE);
  3692.         gTarget := newTarget;
  3693.         fTicksTilNextIdle := 0;                         { Make sure we idle ASAP because there's a
  3694.                                                          new target. }
  3695.         InvalidateCursorRgn;
  3696.         END;
  3697.     END;
  3698.  
  3699. {--------------------------------------------------------------------------------------------------}
  3700. {$S MAApplicationRes}
  3701.  
  3702. PROCEDURE TApplication.SetUndoText(cmdDone: BOOLEAN;
  3703.                                    aCmdNumber: CmdNumber);
  3704.  
  3705.     VAR
  3706.         newMenuState:        integer;
  3707.         undoName:            Str255;
  3708.         cmdName:            Str255;
  3709.         preCmdName:         integer;
  3710.         constChars:         integer;
  3711.  
  3712.     BEGIN
  3713.     IF (gUndoState <> cmdDone) | (gUndoCmd <> aCmdNumber) THEN
  3714.         BEGIN
  3715.         IF aCmdNumber = cCantUndo THEN
  3716.             newMenuState := bzCantUndo
  3717.         ELSE IF cmdDone THEN
  3718.             newMenuState := bzUndo
  3719.         ELSE
  3720.             newMenuState := bzRedo;
  3721.  
  3722.         GetIndString(undoName, kIDBuzzString, newMenuState);
  3723.         IF ParseTitleTemplate(undoName, preCmdName, constChars) THEN
  3724.             BEGIN
  3725.             IF (aCmdNumber = cNoCommand) | (aCmdNumber = cCantUndo) THEN
  3726.                 cmdName := ''
  3727.             ELSE
  3728.                 CmdToName(aCmdNumber, cmdName);
  3729.             IF SubstituteInTitle(undoName, cmdName, preCmdName, constChars) THEN;
  3730.             END;
  3731.  
  3732.         SetCmdName(cUndo, undoName);
  3733.  
  3734.         gUndoState := cmdDone;
  3735.         gUndoCmd := aCmdNumber;
  3736.         END;
  3737.     END;
  3738.  
  3739. {--------------------------------------------------------------------------------------------------}
  3740. {$S MAApplicationRes}
  3741.  
  3742. PROCEDURE TApplication.SetupTheMenus;
  3743.  
  3744.     PROCEDURE DoSetup;
  3745.  
  3746.         VAR
  3747.             appleMenu:            MenuHandle;
  3748.             undoState:            BOOLEAN;
  3749.             undoCmd:            CmdNumber;
  3750.             aWindow:            TWindow;
  3751.             lastCommand:        TCommand;
  3752.             lowSpace:            BOOLEAN;
  3753.  
  3754.         BEGIN
  3755.         IF NOT InModalMenuState THEN
  3756.             BEGIN
  3757.             {$IFC qInspector}
  3758.             lowSpace := MemSpaceIsLow;
  3759.             {$EndC}
  3760.  
  3761.             aWindow := GetActiveWindow;
  3762.             gGotClipType := FALSE;
  3763.  
  3764.             gTarget.DoSetupMenus;                        { Setup menus relevent to target chain }
  3765.  
  3766.             { Set up the menu commands that are not dependent on the target chain… }
  3767.  
  3768.             undoState := kShowCantUndo;                 { Set the Undo menu defaults. }
  3769.             undoCmd := cCantUndo;
  3770.             IF gSysWindowActive THEN
  3771.                 BEGIN
  3772.                 undoState := kShowUndo;
  3773.                 undoCmd := cNoCommand;
  3774.                 Enable(cUndo, TRUE);
  3775.                 Enable(cCut, TRUE);
  3776.                 Enable(cCopy, TRUE);
  3777.                 Enable(cPaste, TRUE);
  3778.                 Enable(cClear, TRUE);
  3779.                 END
  3780.             ELSE
  3781.                 BEGIN
  3782.                 lastCommand := gTarget.GetLastCommand;
  3783.                 IF lastCommand <> NIL THEN
  3784.                     WITH lastCommand DO
  3785.                         IF fCanUndo THEN
  3786.                             BEGIN
  3787.                             IF fCmdDone THEN
  3788.                                 undoState := kShowUndo
  3789.                             ELSE
  3790.                                 undoState := kShowRedo;
  3791.                             undoCmd := fCmdNumber;
  3792.  
  3793.               { Enable Undo only if the last command was not document-specific
  3794.                or the document changed is the current document. }
  3795.                             Enable(cUndo, (fChangedDocument = NIL) | ((aWindow <> NIL) &
  3796.                                    (fChangedDocument = aWindow.fDocument)));
  3797.                             END;
  3798.                 END;
  3799.             SetUndoText(undoState, undoCmd);
  3800.  
  3801.             {!!! we should really just make a call to the debugger/inspector here and give
  3802.             them a shot at setting these up instead }
  3803.             {$IFC qDebug}
  3804.             EnableCheck(cExperimenting, TRUE, gExperimenting);
  3805.             EnableCheck(cReportEvt, TRUE, gReportEvt);
  3806.             EnableCheck(cDebugPrinting, TRUE, gDebugPrinting);
  3807.             EnableCheck(cReportMenuChoices, TRUE, gReportMenuChoices);
  3808.             EnableCheck(cIntenseDebugging, TRUE, gIntenseDebugging);
  3809.             Enable(cIdentifySoftware, TRUE);
  3810.             Enable(cEnterMacAppDebugger, TRUE);
  3811.  
  3812.             IF aWindow <> NIL THEN
  3813.                 BEGIN
  3814.                 Enable(cModalToggle, TRUE);
  3815.                 SetMenuState(cModalToggle, kDebugBuzzStrings, bzMakeModal, bzMakeModeless,
  3816.                              aWindow.fIsModal);
  3817.                 Enable(cRefreshFrontWindow, TRUE);
  3818.                 Enable(cDoFirstClick, TRUE);
  3819.                 SetMenuState(cDoFirstClick, kDebugBuzzStrings, bzDoFirstClick, bzDontDoFirstClick,
  3820.                              aWindow.fDoFirstClick);
  3821.                 END;
  3822.  
  3823.             IF qNeedsROM128k | gConfiguration.hasROM128k THEN
  3824.                 BEGIN
  3825.                 Enable(cSetSysJust, TRUE);
  3826.                 SetMenuState(cSetSysJust, kDebugBuzzStrings, bzSetRightSysJust, bzSetLeftSysJust,
  3827.                              GetActualJustification(teJustSystem) <> teJustLeft);
  3828.                 END;
  3829.  
  3830.             EnableCheck(cTraceSetupMenus, TRUE, gTraceSetupMenus);
  3831.             EnableCheck(cTraceIdle, TRUE, gTraceIdle);
  3832.  
  3833.             Enable(cDebugWind, TRUE);
  3834.             {$ENDC}
  3835.  
  3836.             {$IFC qInspector}
  3837.             Enable(cNewInspectorWindow, NOT lowSpace);
  3838.             {$ENDC}
  3839.  
  3840.             IF NOT gSysWindowActive THEN
  3841.                 Enable(cPaste, gGotClipType);
  3842.             END;
  3843.  
  3844.         appleMenu := MAGetMenu(mApple);
  3845.         WITH appleMenu^^ DO
  3846.             IF Odd(enableFlags) = InModalState THEN
  3847.                 BEGIN
  3848.                 enableFlags := BXOR(enableFlags, 1);
  3849.                 InvalidateMenuBar;
  3850.                 END;
  3851.  
  3852.         END;
  3853.  
  3854.     BEGIN
  3855.     IF MenusHavePendingUpdate | MenuBarHasPendingUpdate THEN
  3856.         PerformMenuSetup(DoSetup);
  3857.     END;
  3858.  
  3859. {--------------------------------------------------------------------------------------------------}
  3860. {$S MAOpen}
  3861.  
  3862. PROCEDURE TApplication.SFGetParms(itsCmdNumber: CmdNumber;
  3863.                                   VAR dlgID: integer;
  3864.                                   VAR where: Point;
  3865.                                   VAR fileFilter, dlgHook, filterProc: ProcPtr;
  3866.                                   typeList: TypeListHandle);
  3867.  
  3868.     VAR
  3869.         dlogTemplate:        DialogTHndl;
  3870.         dialogRect:         Rect;
  3871.  
  3872.     BEGIN
  3873.     dlgID := getDlgID;
  3874.  
  3875.     { compute the top-left location of the dialog }
  3876.     dlogTemplate := DialogTHndl(GetResource('DLOG', dlgID));
  3877.     IF dlogTemplate <> NIL THEN
  3878.         BEGIN
  3879.         dialogRect := dlogTemplate^^.boundsRect;
  3880.         CenterRectOnScreen(dialogRect, TRUE, TRUE, TRUE);
  3881.         where := dialogRect.topLeft;
  3882.         END
  3883.     ELSE
  3884.         SetPt(where, 100, 100);
  3885.  
  3886.     fileFilter := NIL;
  3887.     dlgHook := NIL;
  3888.     filterProc := NIL;
  3889.     SetHandleSize(Handle(typeList), 4);
  3890.     FailMemError;
  3891.     typeList^^[1] := gMainFileType;
  3892.     END;
  3893.  
  3894. {--------------------------------------------------------------------------------------------------}
  3895. {$S MAError}
  3896.  
  3897. PROCEDURE TApplication.ShowError(error: OSErr;
  3898.                                  message: LONGINT);
  3899.  
  3900.     BEGIN
  3901.     ErrorAlert(error, message);
  3902.     END;
  3903.  
  3904. {--------------------------------------------------------------------------------------------------}
  3905. {$S MAApplicationRes}
  3906.  
  3907. PROCEDURE TApplication.SpaceIsLow;
  3908.  
  3909.     VAR
  3910.         now:                LONGINT;
  3911.  
  3912.     BEGIN
  3913.     IF gEventLevel = 1 THEN                             { Don't unload segs if nested event
  3914.                                                          handling}
  3915.         UnloadAllSegments;
  3916.  
  3917.     { Show 'space is low' alert only after ever gLowSpaceInterval ticks. }
  3918.     IF (gLowSpaceInterval > 0) & (NOT gInBackground) THEN
  3919.         BEGIN
  3920.         now := TickCount;
  3921.         IF now > gNextSpaceMsg THEN
  3922.             BEGIN
  3923.             gInhibitNestedHandling := TRUE;             { Don't tell em again from the alert }
  3924.             StdAlert(phSpaceIsLow);
  3925.             gNextSpaceMsg := now + gLowSpaceInterval;
  3926.             END;
  3927.         END;
  3928.     END;
  3929.  
  3930. {--------------------------------------------------------------------------------------------------}
  3931. {$S MAClipboard}
  3932.  
  3933. PROCEDURE TApplication.SwapClipViews;
  3934.  
  3935.     VAR
  3936.         tempClipView:        TView;
  3937.  
  3938.     BEGIN
  3939.     tempClipView := gClipUndoView;
  3940.     gClipUndoView := gClipView;
  3941.  
  3942.     IF tempClipView <> NIL THEN
  3943.         SetClipView(tempClipView)                        { Installs old Undo clipboard as current
  3944.                                                          clipboard }
  3945.         {$IFC qDebug}
  3946.     ELSE
  3947.         ProgramBreak('SwapClipViews finds undo clipboard was NIL')
  3948.         {$ENDC}
  3949.                      ;
  3950.     END;
  3951.  
  3952. {--------------------------------------------------------------------------------------------------}
  3953. {$S MAApplicationRes}
  3954.  
  3955. FUNCTION TApplication.TrackCursor: BOOLEAN;
  3956.  
  3957.     VAR
  3958.         globalMouse:        Point;
  3959.         localMouse:         Point;
  3960.         cursorIsSet:        BOOLEAN;
  3961.         aWMgrWindow:        WindowPtr;
  3962.         cursorWindow:        TWindow;
  3963.         cursorView:         TView;
  3964.         windowVPt:            VPoint;
  3965.         windowBounds:        Rect;
  3966.         r:                    Rect;
  3967.         haveCursorRgn:        BOOLEAN;
  3968.         theActiveWindow:    TWindow;
  3969.         oldPort:            GrafPtr;
  3970.  
  3971.     FUNCTION GetDesktopRect: Rect;
  3972.     { Returns the rgnBBox of the region representing the entire desktop (including menubar). }
  3973.  
  3974.         BEGIN
  3975.         {$IFC qDebug}
  3976.         UseTempRgn('TApplication.TrackCursor, GetDesktopRect');
  3977.         {$ENDC}
  3978.         IF qNeedsColorQD | gConfiguration.hasColorQD THEN { gTempRgn := main screen rect }
  3979.             RectRgn(gTempRgn, GetMainDevice^^.gdRect)
  3980.         ELSE
  3981.             RectRgn(gTempRgn, screenBits.bounds);
  3982.         UnionRgn(GetGrayRgn, gTempRgn, gTempRgn);        { gTempRgn := grayRgn + gTempRgn }
  3983.         GetDesktopRect := gTempRgn^^.rgnBBox;            { return bounding box }
  3984.         {$IFC qDebug}
  3985.         DoneWithTempRgn;
  3986.         {$ENDC}
  3987.         END;
  3988.  
  3989.     PROCEDURE CalcNotClaimedRgn;
  3990.     { Make the region wide open less the active window. And Less Any first click windows or DA's}
  3991.  
  3992.         PROCEDURE DoToWindow(theWMgrWindow: WindowPtr);
  3993.  
  3994.             VAR
  3995.                 aWindow:            TWindow;
  3996.  
  3997.             BEGIN
  3998.             aWindow := WMgrToWindow(theWMgrWindow);
  3999.             IF (aWindow <> NIL) & (aWindow.fDoFirstClick | aWindow.fIsActive) & aWindow.IsShown THEN
  4000.                 DiffRgn(gCursorRgn, WindowPeek(theWMgrWindow)^.contRgn, gCursorRgn);
  4001.             END;
  4002.  
  4003.         BEGIN
  4004.         IF cursorWindow <> NIL THEN
  4005.             WITH globalMouse DO
  4006.                 SetRectRgn(gCursorRgn, h, v, h + 1, v + 1)
  4007.         ELSE
  4008.             BEGIN
  4009.             r := GetDesktopRect;
  4010.             RectRgn(gCursorRgn, r);
  4011.             EachWMgrWindowDo(DoToWindow);
  4012.             { make sure mouse's current location is included }
  4013.             {$IFC qDebug}
  4014.             UseTempRgn('TApplication.TrackCursor, CalcNotClaimedRgn');
  4015.             {$ENDC}
  4016.             WITH globalMouse DO
  4017.                 SetRectRgn(gTempRgn, h, v, h + 1, v + 1);
  4018.             UnionRgn(gTempRgn, gCursorRgn, gCursorRgn);
  4019.             {$IFC qDebug}
  4020.             DoneWithTempRgn;
  4021.             {$ENDC}
  4022.             END;
  4023.         END;
  4024.  
  4025.     BEGIN
  4026.     TrackCursor := FALSE;
  4027.  
  4028.     IF gInBackground THEN
  4029.         EXIT(TrackCursor);
  4030.  
  4031.     GetMouse(globalMouse);
  4032.     LocalToGlobal(globalMouse);
  4033.  
  4034.     IF PtInRgn(globalMouse, gCursorRgn) THEN
  4035.         BEGIN
  4036.         {$IFC qDebug}
  4037.         IF gIntenseDebugging & gTraceIdle THEN
  4038.             Writeln('cursor is in cursor region');
  4039.         {$ENDC}
  4040.         IF NOT gAlwaysTrackCursor THEN
  4041.             EXIT(TrackCursor);
  4042.         END;
  4043.  
  4044.     InvalidateCursorRgn;
  4045.     haveCursorRgn := FALSE;
  4046.     cursorIsSet := FALSE;
  4047.  
  4048.  { Find out if the cursor is in a window.  If it is the window must be the
  4049.   front window or must handle first clicks.
  4050.   ??? Shouldn't the cursor testing be handed off to the window!!! }
  4051.  
  4052.     theActiveWindow := GetActiveWindow;
  4053.  
  4054.     IF (FindWindow(globalMouse, aWMgrWindow) = inContent) THEN
  4055.         BEGIN
  4056.         GetPort(oldPort);
  4057.         SetPort(aWMgrWindow);
  4058.         localMouse := globalMouse;
  4059.         GlobalToLocal(localMouse);
  4060.         SetPort(oldPort);
  4061.  
  4062.         cursorWindow := WMgrToWindow(aWMgrWindow);
  4063.         IF (NOT PtInRgn(localMouse, aWMgrWindow^.visRgn)) | ((cursorWindow <> NIL) &
  4064.            (cursorWindow <> theActiveWindow) & (NOT cursorWindow.fDoFirstClick)) THEN
  4065.             cursorWindow := NIL;
  4066.         END
  4067.     ELSE
  4068.         cursorWindow := NIL;
  4069.  
  4070.     IF cursorWindow <> NIL THEN
  4071.         BEGIN
  4072.         cursorWindow.GetGlobalBounds(windowBounds);
  4073.         windowVPt.h := globalMouse.h - windowBounds.left;
  4074.         windowVPt.v := globalMouse.v - windowBounds.top;
  4075.         cursorView := cursorWindow.HandleCursor(windowVPt, gCursorRgn);
  4076.         IF cursorView <> NIL THEN
  4077.             BEGIN
  4078.             cursorIsSet := TRUE;
  4079.  
  4080.             IF NOT EmptyRgn(gCursorRgn) THEN
  4081.                 BEGIN
  4082.                 haveCursorRgn := TRUE;
  4083.  
  4084.                 { Intersect with viewed rect }
  4085.                 IF qDebug THEN
  4086.                     cursorView.AssumeFocused;
  4087.  
  4088.                 { Intersect with visible region }
  4089.                 SectRgn(thePort^.visRgn, gCursorRgn, gCursorRgn);
  4090.                 SectRgn(thePort^.clipRgn, gCursorRgn, gCursorRgn);
  4091.  
  4092.                 { Convert gCursorRgn from view coords to global coords }
  4093.                 WITH thePort^.portRect DO
  4094.                     OffsetRgn(gCursorRgn, windowBounds.left - left, windowBounds.top - top);
  4095.                 END;
  4096.             END;
  4097.         END;
  4098.  
  4099.     IF NOT haveCursorRgn THEN
  4100.         CalcNotClaimedRgn;
  4101.  
  4102.     {$IFC qDebug}
  4103.     IF gIntenseDebugging & gTraceIdle THEN
  4104.         IF gCursorRgn = NIL THEN
  4105.             Writeln('gCursorRgn is NIL')
  4106.         ELSE
  4107.             BEGIN
  4108.             HLock(Handle(gCursorRgn));
  4109.             WrLblRect('gCursorRgn', gCursorRgn^^.rgnBBox);
  4110.             Writeln;
  4111.             HUnlock(Handle(gCursorRgn));
  4112.             END;
  4113.     {$ENDC}
  4114.  
  4115.     IF NOT cursorIsSet THEN
  4116.         SetCursor(arrow);
  4117.     TrackCursor := cursorIsSet;
  4118.  
  4119.     IF NOT PtInRgn(globalMouse, gCursorRgn) THEN
  4120.         BEGIN
  4121.         IF qDebug THEN
  4122.             BEGIN
  4123.             Writeln('Whoops, cursor region was not correctly calculated.');
  4124.             WrLblPt('global cursor', globalMouse);
  4125.             WrLblRect('  gCursorRgn^^.rgnBBox', gCursorRgn^^.rgnBBox);
  4126.             Writeln;
  4127.             ProgramBreak(
  4128.                         'The cursor is not in the cursor region at end of TApplication.TrackCursor!'
  4129.                          );
  4130.             END;
  4131.         END;
  4132.  
  4133.     END;
  4134.  
  4135. {--------------------------------------------------------------------------------------------------}
  4136. {$S MADoCommand}
  4137.  
  4138. FUNCTION TApplication.TrackMouse(globalMouse, hysteresis: Point;
  4139.                                  theCommand: TCommand): TCommand;
  4140.  
  4141.     VAR
  4142.         tracker:            TCommand;
  4143.         view:                TView;
  4144.         scroller:            TScroller;
  4145.         gotATracker:        BOOLEAN;
  4146.         theQDMouse:         Point;
  4147.         theMouse:            VPoint;
  4148.         anchorPoint:        VPoint;
  4149.         previousPoint:        VPoint;
  4150.         peekEvent:            EventRecord;
  4151.         movedOnce:            BOOLEAN;
  4152.         amtMoved:            VPoint;
  4153.         didMove:            BOOLEAN;
  4154.         delta:                VPoint;
  4155.         mouseInScroller:    VPoint;
  4156.         didScroll:            BOOLEAN;
  4157.         currTranslation:    VPoint;
  4158.         viewExtent:         VRect;
  4159.         autoscrollLimit:    VRect;
  4160.         focusedOnDesktop:    BOOLEAN;
  4161.         desktopPort:        CGrafPort;
  4162.         savedPort:            GrafPtr;
  4163.  
  4164.     PROCEDURE CleanUpFocus;
  4165.  
  4166.         BEGIN
  4167.         IF focusedOnDesktop THEN
  4168.             BEGIN
  4169.             IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  4170.                 CloseCPort(@desktopPort)
  4171.             ELSE
  4172.                 ClosePort(@desktopPort);
  4173.             SetPort(savedPort);
  4174.             focusedOnDesktop := FALSE;
  4175.             END;
  4176.         END;
  4177.  
  4178.     PROCEDURE SetupFocus;
  4179.  
  4180.         BEGIN
  4181.         IF view <> NIL THEN
  4182.             BEGIN
  4183.             IF focusedOnDesktop THEN
  4184.                 CleanUpFocus;
  4185.  
  4186.             IF view.Focus THEN
  4187.                 BEGIN
  4188.                 GetFocus(gSaveFocusRec);
  4189.                 IF scroller <> NIL THEN
  4190.                     BEGIN
  4191.                     scroller.GetExtent(autoscrollLimit);
  4192.                     currTranslation := scroller.fTranslation;
  4193.                     END;
  4194.                 END
  4195.                 {$IFC qDebug}
  4196.             ELSE
  4197.                 ProgramBreak('TApplication.TrackMouse: Unable to focus view.')
  4198.                 {$ENDC}
  4199.                              ;
  4200.             END
  4201.         ELSE
  4202.             BEGIN                                        { focus on the desktop }
  4203.             IF NOT focusedOnDesktop THEN
  4204.                 BEGIN
  4205.                 GetPort(savedPort);                     { In case we exit still focusedOnDeskTop }
  4206.                 IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  4207.                     OpenCPort(@desktopPort)
  4208.                 ELSE
  4209.                     OpenPort(@desktopPort);
  4210.                 focusedOnDesktop := TRUE;
  4211.                 END;
  4212.  
  4213.             CopyRgn(GetGrayRgn, desktopPort.visRgn);
  4214.             desktopPort.portRect := desktopPort.visRgn^^.rgnBBox;
  4215.             InvalidateFocus;
  4216.             GetFocus(gSaveFocusRec);
  4217.             END;
  4218.         END;
  4219.  
  4220.     PROCEDURE DoFocus;
  4221.  
  4222.         BEGIN
  4223.         {$Push} {$H-}
  4224.         IF (scroller <> NIL) & NOT EqualVPt(currTranslation, scroller.fTranslation) THEN
  4225.         {$Pop}
  4226.             SetupFocus
  4227.         ELSE
  4228.             SetFocus(gSaveFocusRec);
  4229.         END;
  4230.  
  4231.     PROCEDURE InstallTracker(newTracker: TCommand);
  4232.  
  4233.         BEGIN
  4234.         tracker := newTracker;
  4235.         gotATracker := (tracker <> NIL);
  4236.         IF gotATracker THEN
  4237.             BEGIN
  4238.             view := tracker.fView;
  4239.             scroller := tracker.fScroller;
  4240.             IF view <> NIL THEN
  4241.                 view.GetExtent(viewExtent);
  4242.             SetupFocus;
  4243.             END;
  4244.         END;
  4245.  
  4246.     PROCEDURE FeedbackOnce(turnItOn, mouseDidMove: BOOLEAN);
  4247.  
  4248.         BEGIN
  4249.         IF gotATracker THEN
  4250.             BEGIN
  4251.             PenNormal;
  4252.             PenMode(PatXOR);
  4253.             tracker.TrackFeedback(anchorPoint, previousPoint, turnItOn, mouseDidMove);
  4254.             END;
  4255.         END;
  4256.  
  4257.     PROCEDURE ConstrainOnce;                            { ??? fold this into TrackOnce ??? }
  4258.  
  4259.         BEGIN
  4260.         IF gotATracker THEN
  4261.             BEGIN
  4262.             IF tracker.fViewConstrain & (view <> NIL) THEN
  4263.                 PinVRect(viewExtent, theMouse);
  4264.             IF tracker.fConstrainsMouse THEN
  4265.                 tracker.TrackConstrain(anchorPoint, previousPoint, theMouse);
  4266.             END;
  4267.         END;
  4268.  
  4269.     PROCEDURE TrackOnce(aTrackPhase: TrackPhase;
  4270.                         didMouseMove: BOOLEAN);
  4271.  
  4272.         VAR
  4273.             newTracker:         TCommand;
  4274.  
  4275.         BEGIN
  4276.         {$IFC qDebug}
  4277.         IF tracker = NIL THEN
  4278.             BEGIN
  4279.             ProgramBreak('In TApplication.TrackMouse: tracker = NIL');
  4280.             tracker := NIL;
  4281.             gotATracker := FALSE;
  4282.             END;
  4283.         {$ENDC}
  4284.  
  4285.         IF gotATracker THEN
  4286.             BEGIN
  4287.             newTracker := tracker.TrackMouse(aTrackPhase, anchorPoint, previousPoint, theMouse,
  4288.                                              didMouseMove);
  4289.             IF newTracker <> tracker THEN
  4290.                 BEGIN
  4291.                 FreeIfObject(tracker);
  4292.                 tracker := NIL;
  4293.  
  4294.                 InstallTracker(newTracker);
  4295.                 END
  4296.             ELSE IF (newTracker <> NIL) & (newTracker.fView <> view) THEN
  4297.                 InstallTracker(newTracker);
  4298.             END;
  4299.         END;
  4300.  
  4301.     BEGIN
  4302.     focusedOnDesktop := FALSE;
  4303.     InstallTracker(theCommand);
  4304.  
  4305.     theQDMouse := globalMouse;
  4306.     IF view <> NIL THEN
  4307.         BEGIN
  4308.         GlobalToLocal(theQDMouse);
  4309.         view.QDToViewPt(theQDMouse, theMouse);
  4310.         END
  4311.     ELSE
  4312.         PtToVPt(theQDMouse, theMouse);
  4313.     anchorPoint := theMouse;
  4314.     previousPoint := theMouse;
  4315.  
  4316.     ConstrainOnce;
  4317.  
  4318.     anchorPoint := theMouse;
  4319.     previousPoint := theMouse;                            { in case Constrain changed the localPoint;
  4320.                                                          guarantee that all 3 are the same on
  4321.                                                          TrackPress }
  4322.  
  4323.     TrackOnce(trackPress, TRUE);
  4324.     previousPoint := theMouse;                            { in case TrackMouse changed nextPoint }
  4325.     FeedbackOnce(TRUE, TRUE);
  4326.  
  4327.     movedOnce := FALSE;
  4328.  
  4329.     WHILE gotATracker & NOT tracker.IsDoneTracking DO
  4330.         BEGIN
  4331.         DoFocus;
  4332.         GetMouse(theQDMouse);
  4333.         IF view <> NIL THEN
  4334.             view.QDToViewPt(theQDMouse, theMouse)
  4335.         ELSE
  4336.             PtToVPt(theQDMouse, theMouse);
  4337.  
  4338.         IF NOT movedOnce THEN
  4339.             BEGIN
  4340.             ConstrainOnce;                                { ensure that we are playing on a level
  4341.                                                          field. }
  4342.             amtMoved := theMouse;
  4343.             SubVPt(anchorPoint, amtMoved);
  4344.             IF (Abs(amtMoved.h) >= hysteresis.h) | (Abs(amtMoved.v) >= hysteresis.v) THEN
  4345.                 movedOnce := TRUE;
  4346.             END;
  4347.  
  4348.         delta := gZeroVPt;
  4349.         IF movedOnce | tracker.fTrackNonMovement THEN
  4350.             BEGIN
  4351.  
  4352.             { ??? Problems with this:
  4353.             delta might be non-zero but scrolling can't take place
  4354.             because it is pinned at the end of the view
  4355.             also might want some slop before scrolling ??? }
  4356.  
  4357.             IF (scroller <> NIL) & (view <> NIL) THEN
  4358.                 BEGIN
  4359.                 mouseInScroller := theMouse;
  4360.                 view.LocalToWindow(mouseInScroller);
  4361.                 scroller.WindowToLocal(mouseInScroller);
  4362.                 IF NOT PtInVRect(mouseInScroller, autoscrollLimit) THEN
  4363.                     BEGIN
  4364.                     scroller.AutoScroll(mouseInScroller, delta); { Get the amount to autoscroll, if any }
  4365.                     AddVPt(delta, theMouse);
  4366.                     END;
  4367.                 END;
  4368.  
  4369.             ConstrainOnce;
  4370.             END;
  4371.  
  4372.         didScroll := NOT EqualVPt(delta, gZeroVPt);
  4373.         didMove := NOT EqualVPt(previousPoint, theMouse);
  4374.  
  4375.         FeedbackOnce(FALSE, didMove | didScroll);
  4376.  
  4377.         IF didScroll THEN
  4378.             BEGIN
  4379.             tracker.AutoScroll(delta.h, delta.v);    { OK, now actually do the scrolling }
  4380.             IF view <> NIL THEN
  4381.                 view.Update;                        { Keep synchronized.  ScrollDraw only invalidated }
  4382.             SetupFocus;                                 { the focus changed }
  4383.             END;
  4384.  
  4385.         TrackOnce(trackMove, didMove);                    { ??? add OR didscroll ??? }
  4386.  
  4387.         previousPoint := theMouse;
  4388.         FeedbackOnce(TRUE, didMove | didScroll);
  4389.         END;
  4390.  
  4391.     DoFocus;
  4392.  
  4393.     IF NOT movedOnce THEN
  4394.         theMouse := previousPoint                        { normally same as original mouse down; we
  4395.                                                          don't use anchorPoint in case someone has
  4396.                                                          changed that -- it is more likely that an
  4397.                                                          app would change anchorPoint than
  4398.                                                          previousPoint }
  4399.  
  4400.     ELSE IF EventAvail(mUpMask + mDownMask, peekEvent) THEN
  4401.         BEGIN
  4402.         theQDMouse := peekEvent.where;
  4403.         IF view <> NIL THEN
  4404.             BEGIN
  4405.             GlobalToLocal(theQDMouse);
  4406.             view.QDToViewPt(theQDMouse, theMouse);
  4407.             END
  4408.         ELSE
  4409.             PtToVPt(theQDMouse, theMouse);
  4410.         ConstrainOnce;
  4411.         END;
  4412.     { ELSE we use the last known mouse position }
  4413.  
  4414.     FeedbackOnce(FALSE, TRUE);
  4415.     TrackOnce(trackRelease, TRUE);
  4416.  
  4417.     CleanUpFocus;
  4418.  
  4419.     TrackMouse := tracker;
  4420.  
  4421.     END;
  4422.  
  4423. {--------------------------------------------------------------------------------------------------}
  4424. {$S MAApplicationRes}
  4425.  
  4426. PROCEDURE TApplication.UpdateAllWindows;
  4427.  
  4428.     CONST
  4429.         systemEventMask     = app4Mask;                 { maybe this will be defined in the
  4430.                                                          interfaces someday }
  4431.  
  4432.     VAR
  4433.         anEvent:            EventRecord;
  4434.  
  4435.     BEGIN
  4436.     WHILE GetEvent(updateMask + activMask + systemEventMask, 0, NIL, anEvent) DO { SystemEvents
  4437.               aren't queued }
  4438.         HandleEvent(anEvent);
  4439.     END;
  4440.  
  4441. {--------------------------------------------------------------------------------------------------}
  4442. {$S MAApplicationRes}
  4443.  
  4444. FUNCTION TApplication.WMgrToWindow(aWMgrWindow: WindowPtr): TWindow;
  4445.  
  4446.     BEGIN
  4447.     IF (aWMgrWindow <> NIL) & (NOT IsDeskAccessory(aWMgrWindow))
  4448.     { Make an IsObject test too because some slimedog may have created a window in our
  4449.     world and the refcon wouldn't be an object.  Since this is the only place in
  4450.     MacApp that we get asked to do something to a ToolBox structure where we don't _know_
  4451.     that we created the structure we need to be especially careful here.  ??? Perhaps in the
  4452.     future we should use a dictionary to make the windowPtr to TWindow association for us. }
  4453.        & IsObject(GetWRefCon(aWMgrWindow)) THEN
  4454.         WMgrToWindow := TWindow(GetWRefCon(aWMgrWindow))
  4455.     ELSE
  4456.         WMgrToWindow := NIL;
  4457.     END;
  4458.